TLDR;如果我的Go gRPC双向流服务器无限循环Recv
/ 循环Send
,当客户端stream
超出范围并发生GC 时,如何关闭连接?
假设我正在使用Go进行gRPC双向流式调用:
syntax = "proto3";
package mystical;
service Unicorn {
rpc RainbowStream(stream Rainbow) returns (stream Rainbow);
}
我有一个服务器实现,将在我的gRPC服务器中注册:
type Server struct {}
func (serv *Server) RainbowStream(stream proto.Unicorn_RainbowStreamServer) error {
// Stub implementation
// Just sends the rainbows back
for {
msg, err := stream.Recv()
if err != nil {
return err
}
if err := stream.Send(msg); err != nil {
return err
}
}
}
然后,我有一个客户端,消除了一些gRPC的细节:
type Client struct {
proto.UnicornClient
}
func (c *Client) TastyColors() (stream proto.Unicorn_RainbowStreamClient, err error) {
return c.RainbowStream()
}
我这样做:
func somewhereDeepInMyCode() {
stream, err := aClient.TastyColors()
// ...
go func() {
stream.Send(msg)
// ...
// eventually this goroutine ends
// and `stream` would get GC'd
}
}
当stream
超出范围时,gRPC流式调用会自行清理吗?通常,据我了解,服务器必须返回RainbowStream
调用以关闭连接。如果它不能自行清理,该如何实现?
使用取消(https://golang.org/pkg/context/#WithCancel)上下文从客户端取消:
func somewhereDeepInMyCode() {
ctx, cancel := context.WithCancel(context.Background())
stream, err := aClient.TastyColors(ctx)
// ...
go func() {
defer cancel()
stream.Send(msg)
// ...
// eventually this goroutine ends
// and `stream` would get GC'd
}
}
服务器可以根据需要处理客户端取消操作以进行清理:
for {
select {
...
case <-stream.Context().Done():
// cleanup
...
}
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句