【发布时间】:2020-09-09 23:04:52
【问题描述】:
对于 Go 和 GRPC 来说都是新手,所以请耐心等待。
使用 go 版本 go1.14.4 windows/amd64、proto3 和最新的 grpc(我认为是 1.31)。我正在尝试建立一个可能会打开更长时间的双向流连接。一切都在本地工作,除非我终止客户端(或其中一个),它也会杀死服务器并出现以下错误:
无法交易数据 rpc 错误:代码 = 已取消 desc = 上下文已取消
此错误来自此代码服务器端
func (s *exchangeserver) Trade(stream proto.ExchageService_TradeServer) error {
endchan := make(chan int)
defer close(endchan)
go func() {
for {
req, err := stream.Recv()
if err == io.EOF {
break
}
if err != nil {
log.Fatal("Unable to trade data ", err)
break
}
fmt.Println("Got ", req.GetNumber())
}
endchan <- 1
}()
go func() {
for {
resp := &proto.WordResponse{Word: "Hello again "}
err := stream.Send(resp)
if err != nil {
log.Fatal("Unable to send from server ", err)
break
}
time.Sleep(time.Duration(500 * time.Millisecond))
}
endchan <- 1
}()
<-endchan
return nil
}
而且 Trade() RPC 非常简单,不值得发布 .proto。 该错误显然来自 Recv() 调用,但该调用会阻塞,直到它看到一条消息,例如客户端断开连接,此时我希望它会终止流,而不是整个过程。我尝试使用 HandleConn(context, stats.ConnStats) 添加服务处理程序,它确实在服务器死机之前捕获了断开连接,但我无能为力。我什至尝试创建一个全局通道,当调用 HandleRPC(context, stats.RPCStats) 时,服务处理程序会将值推送到该通道中,并且仅在通道中有值时才允许调用 Recv() ,但这不能是的,这就像为了安全而阻止了一个阻塞函数,但它无论如何都不起作用。
这一定是初学者犯的那些真正愚蠢的错误之一。如果 GPRC 不能在不死的情况下处理客户端断开连接,那么它有什么用呢?然而,我已经从互联网的每个角落阅读了可能一万亿(ish)的帖子,没有其他人遇到这个问题。相反,这个问题更流行的版本是“我的客户端流在断开连接后保持打开状态”。我期待这个问题。不是这个。
【问题讨论】:
标签: go network-programming grpc-go