go - golang 中 server.GracefulStop() 的行为

标签 go server grpc goroutine grpc-go

我有一个 gRPC 服务器,我已经实现了像这样正常关闭我的 gRPC 服务器

fun main() {
    //Some code
    term := make(chan os.Signal)
    go func() {
            if err := grpcServer.Serve(lis); err != nil {
                term <- syscall.SIGINT
            }
        }()

    signal.Notify(term, syscall.SIGTERM, syscall.SIGINT)
    <-term
    server.GracefulStop()
    closeDbConnections()
}

这很好用。 相反,如果我在主 goroutine 中编写 grpcServer.Serve() 逻辑并将关闭处理程序逻辑放入另一个 goroutine,则 server.GracefulStop() 之后的语句通常不会执行.如果完全执行 closeDbConnections(),一些 DbConnections 将关闭。

server.GracefulStop() 是一个阻塞调用。绝对 grpcServer.Serve()server.GracefulStop() 完成之前完成。那么,这个调用返回后,main goroutine 需要多长时间才能停止?

有问题的代码

func main() {
    term := make(chan os.Signal)
    go func() {
        signal.Notify(term, syscall.SIGTERM, syscall.SIGINT)
        <-term
        server.GracefulStop()
        closeDbConnections()
    }()
    if err := grpcServer.Serve(lis); err != nil {
        term <- syscall.SIGINT
    }
}

这个案例没有按预期工作。 server.GracefulStop() 完成后,closeDbConnections() 可能运行也可能不运行(通常不会运行完成)。我通过从我的终端按 Ctrl-C 发送 SIGINT 来测试后一种情况。

有人可以解释一下这种行为吗?

最佳答案

我不确定你的问题(请澄清),但我建议你以这种方式重构你的main:

func main() {

   // ...

   errChan := make(chan error)
   stopChan := make(chan os.Signal)

   // bind OS events to the signal channel
   signal.Notify(stopChan, syscall.SIGTERM, syscall.SIGINT)

   // run blocking call in a separate goroutine, report errors via channel
   go func() {
        if err := grpcServer.Serve(lis); err != nil {
            errChan <- err
        }
    }()

   // terminate your environment gracefully before leaving main function
   defer func() {
      server.GracefulStop()
      closeDbConnections()
   }()

   // block until either OS signal, or server fatal error
   select {
      case err := <-errChan:
          log.Printf("Fatal error: %v\n", err) 
      case <-stopChan:
   }

我不认为混合系统事件和服务器错误是个好主意,就像您在示例中所做的那样:如果 Serve 失败,您只需忽略错误并发出系统事件,实际上并没有发生。当导致进程终止的两种不同类型的事件有两种传输( channel )时,请尝试另一种方法。

关于go - golang 中 server.GracefulStop() 的行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55797865/

相关文章:

Golang gRPC 服务器流

heroku - Heroku 是否支持 RPC(即 gRPC)?

带证书的 Golang Opc UA 客户端实现

C TCP/IP 服务器绑定(bind)错误 -- 非套接字上的套接字操作

java - Kotlin上的Server-Client应用程序出现问题

macos - 无法在 xampp 上找到 htdocs

go - 如何搜索所有未读邮件 IMAP CMD/go

go - 如何转换图像以上传 Spotify 个人资料图片?

mongodb - 简单查询的上下文

python - gRPC python 客户端身份验证示例