当前位置: 首页 > 面试题库 >

如何使用gracefulStop关闭所有grpc服务器流?

金阳华
2023-03-14
问题内容

我正在尝试停止从服务器端连接到流服务器的所有客户端。其实我正在使用GracefulStop方法来优雅地处理它。

我正在等待os.Interrupt通道上的信号以对gRPC执行正常停止。但是server.GracefulStop()当客户端连接时会卡住。

func (s *Service) Subscribe(_ *empty.Empty, srv clientapi.ClientApi_SubscribeServer) error {
    ctx := srv.Context()

    updateCh := make(chan *clientapi.Update, 100)
    stopCh := make(chan bool)
    defer func() {
        stopCh<-true
        close(updateCh)
    }

    go func() {
        ticker := time.NewTicker(1 * time.Second)
        defer func() {
            ticker.Stop()
            close(stopCh)
        }
        for {
            select {
            case <-stopCh:
                return
            case <-ticker.C:
                updateCh<- &clientapi.Update{Name: "notification": Payload: "sample notification every 1 second"}
            }
        }
    }()

    for {
        select {
        case <-ctx.Done():
            return ctx.Err()

        case notif := <-updateCh:
            err := srv.Send(notif)
            if err == io.EOF {
                return nil
            }

            if err != nil {
                s.logger.Named("Subscribe").Error("error", zap.Error(err))
                continue
            }
        }
    }
}

我希望contextin方法ctx.Done()可以处理它并中断for循环。如何关闭像这样的所有响应流?


问题答案:

为您的gRPC服务创建一个 全局 context变量。因此,遍历各个部分:

  • 每个gRPC服务html" target="_blank">请求都将使用此上下文(以及客户端上下文)来满足该请求
  • os.Interrupt处理程序将取消全局上下文;从而取消任何当前正在运行的请求
  • 最终问题server.GracefulStop()-应该等待所有活动的gRPC调用完成(如果他们没有立即看到取消操作)

因此,例如,在设置gRPC服务时:

pctx := context.Background()
globalCtx, globalCancel := context.WithCancel(pctx)

mysrv := MyService{
    gctx: globalCtx
}

s := grpc.NewServer()
pb.RegisterMyService(s, mysrv)

os.Interrupt 处理程序启动并等待关闭:

globalCancel()
server.GracefulStop()

gRPC方法:

func(s *MyService) SomeRpcMethod(ctx context.Context, req *pb.Request) error {

    // merge client and server contexts into one `mctx`
    // (client context will cancel if client disconnects)
    // (server context will cancel if service Ctrl-C'ed)

    mctx, mcancel := mergeContext(ctx, s.gctx)

    defer mcancel() // so we don't leak, if neither client or server context cancels

    // RPC WORK GOES HERE
    // RPC WORK GOES HERE
    // RPC WORK GOES HERE

    // pass mctx to any blocking calls:
    // - http REST calls
    // - SQL queries etc.
    // - or if running a long loop; status check the context occasionally like so:

    // Example long request (10s)
    for i:=0; i<10*1000; i++ {
        time.Sleep(1*time.Milliscond)

        // poll merged context
        select {
            case <-mctx.Done():
                return fmt.Errorf("request canceled: %s", mctx.Err())
            default:
        }
    }
}

和:

func mergeContext(a, b context.Context) (context.Context, context.CancelFunc) {
    mctx, mcancel := context.WithCancel(a) // will cancel if `a` cancels

    go func() {
        select {
        case <-mctx.Done(): // don't leak go-routine on clean gRPC run
        case <-b.Done():
            mcancel() // b canceled, so cancel mctx 
        }
    }()

    return mctx, mcancel
}


 类似资料:
  • 我已经尝试了一段时间试图关闭ChromeDriver服务,但我无法开发如何关闭的解决方案。我正在使用摩卡和柴进行单元测试。第一个测试通过,第二个由于错误而失败。 我试着在selenium webdrive/chrome中查找。js模块,无法找到关闭服务的函数。我试着搜索答案,但在网上也找不到任何答案。也许我创建chrome驱动程序的方法需要重新设计。我尝试使用“selenium webdriver

  • 我正在使用收集器跟踪java服务中的跨度,这一服务是http和grpc。收集器终结点是localhost:55680。此java服务跟踪成功。 现在,我想使用这个收集器基于gRPC跟踪我的go服务。 在我的go服务中,我复制以下文件:interceptor。去grpctrace。从repo opentelemetry转到contrib,这里https://github.com/open-telem

  • gRPC新手,找不到任何关于如何在服务器端启用SSL的例子。我使用openssl生成了一个密钥对,但是它报错说私钥无效。 这是我的代码

  • 问题内容: 我有一个包含http(s)服务器的Node.js应用程序。 在特定情况下,我需要以编程方式关闭此服务器。我当前正在做的是调用其函数,但这无济于事,因为它会等待所有保持活动的连接首先完成。 因此,基本上,这将关闭服务器,但仅在最少等待120秒之后。但是我希望服务器立即关闭-即使这意味着要中断当前处理的请求。 我不能做的是一个简单的 因为服务器只是应用程序的一部分,应用程序的其余部分应保持

  • 问题内容: 我需要从 网址获得回调后关闭服务器。使用通常的 HTTP API, 关闭服务器当前支持 API功能,但是使用节点表达服务器时 出现错误。而且我不知道如何找到解决此问题的信息。 我应该如何关闭快递服务器? NodeJS配置说明: 实际应用代码: 另外,我发现[‘nodejs expressclose…’,]但是我不确定是否可以将其用于具有以下代码的代码中:。 问题答案: 返回。您应该在该

  • Apache版本和模块: 我使用grpc服务器作为后端服务器,由Apache代理。Apache用于终止TLS连接(在Apache中添加了http2支持)。以下是代理设置: ProxyPassMatch“^/v3”h2c://127.0.0.1:9080 现在,如果我发送一个有效的grpc客户端请求,它将被Apache成功代理,grpc客户端将收到grpc服务器响应。但是,当我试图发送一个在grpc