agy*_*eya 0 go goroutine server grpc 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()
}
Run Code Online (Sandbox Code Playgroud)
这很好用。如果我grpcServer.Serve()在主 goroutine 中编写逻辑,并将关闭处理程序逻辑放入另一个 goroutine 中,则之后的语句server.GracefulStop()通常不会执行。一些 DbConnections 如果closeDbConnections()执行的话,会被关闭。
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
}
}
Run Code Online (Sandbox Code Playgroud)
这种情况没有按预期工作。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:
}
Run Code Online (Sandbox Code Playgroud)
我认为混合系统事件和服务器错误不是一个好主意,就像您在示例中所做的那样:如果Serve失败,您只需忽略错误并发出系统事件,而这实际上并没有发生。当两种不同类型的事件有两种传输(通道)导致进程终止时,请尝试另一种方法。
| 归档时间: |
|
| 查看次数: |
6177 次 |
| 最近记录: |