编程网今天将给大家带来《gRPC 上下文取消传播》,感兴趣的朋友请继续看下去吧!以下内容将会涉及到等等知识点,如果你是正在学习Golang或者已经是大佬级别了,都非常欢迎也希望大家都能给我建议评论哈~希望能帮助到大家!
问题内容我试图了解 Go 上下文取消在客户端服务通信(例如任何 gRPC API 调用)中是如何工作的。
假设客户端取消了上下文。这是否会导致向服务器发出新的 HTTP 请求,并取消先前/正在进行的 gRPC 请求的上下文?服务器如何知道客户端是否取消了上下文?
正确答案
默认情况下,http2
用作 gprc 的底层协议。 http2
连接上可能有多个流。这是一张图片,说明了来自 web dev 的 http2
的连接和流
如果您在响应返回之前取消一个 grpc 调用中的上下文。客户端的 errcode 可能是 cancel
和 mapping to RST_STREAM
,然后这个 rst_stream
将被发送到服务器。 rst_stream
帧允许立即终止流,即当前的 rpc 调用流将被终止。但是,http2
连接仍然存在,当调用下一个 rpc 调用时,将使用另一个新流来执行 rpc 调用。
这里是一些测试代码片段。
客户端:100毫秒后强制取消上下文。
conn, err := grpc.dial(serveraddr,
grpc.withtransportcredentials(insecure.newcredentials()))
defer conn.close()
c := pb.newgreeterclient(conn)
for i := 0; i < 10; i++ {
ctx, cancel := context.withcancel(context.todo())
go func() {
// force call cancel after 100 milliseconds
time.sleep(100 * time.millisecond)
cancel()
}()
r, err := c.sayhello(ctx, &pb.hellorequest{name: "name"})
}
服务器端:延迟sayhello响应1秒。
func (s *server) sayhello(ctx context.context, in *pb.hellorequest) (*pb.helloreply, error) {
// delay ack on server by 1 seconds
randms := 1000
select {
case <-time.after(time.duration(randms) * time.millisecond):
case <-ctx.done():
if ctx.err() == context.canceled || ctx.err() == context.deadlineexceeded {
log.printf("sayhello: context err %+v \n", ctx.err())
return nil, ctx.err()
}
}
使用 godebug=http2debug=2
运行代码,更多grpc的调试日志可以帮助我们了解客户端和服务器之间的消息。
客户端日志
2022/10/21 20:40:38 http2: Framer 0xc0005be000: wrote SETTINGS len=0
2022/10/21 20:40:38 http2: Framer 0xc0005be000: read SETTINGS len=6, settings: MAX_FRAME_SIZE=16384
2022/10/21 20:40:38 http2: Framer 0xc0005be000: wrote SETTINGS flags=ACK len=0
2022/10/21 20:40:38 http2: Framer 0xc0005be000: read SETTINGS flags=ACK len=0
2022/10/21 20:40:38 http2: Framer 0xc0005be000: wrote HEADERS flags=END_HEADERS stream=1 len=98
2022/10/21 20:40:38 http2: Framer 0xc0005be000: wrote DATA flags=END_STREAM stream=1 len=12 data="\x00\x00\x00\x00\a\n\x05world"
2022/10/21 20:40:38 http2: Framer 0xc0005be000: read WINDOW_UPDATE len=4 (conn) incr=12
2022/10/21 20:40:38 http2: Framer 0xc0005be000: read PING len=8 ping="\x02\x04\x10\x10\t\x0e\a\a"
2022/10/21 20:40:38 http2: Framer 0xc0005be000: wrote PING flags=ACK len=8 ping="\x02\x04\x10\x10\t\x0e\a\a"
force call cancel in client
2022/10/21 20:40:38 could not greet: rpc error: code = Canceled desc = context canceled
2022/10/21 20:40:38 http2: Framer 0xc0005be000: wrote RST_STREAM stream=1 len=4 ErrCode=CANCEL
2022/10/21 20:40:41 http2: Framer 0xc0005be000: wrote HEADERS flags=END_HEADERS stream=3 len=7
2022/10/21 20:40:41 http2: Framer 0xc0005be000: wrote DATA flags=END_STREAM stream=3 len=12 data="\x00\x00\x00\x00\a\n\x05world"
2022/10/21 20:40:41 http2: Framer 0xc0005be000: read WINDOW_UPDATE len=4 (conn) incr=12
2022/10/21 20:40:41 http2: Framer 0xc0005be000: read PING len=8 ping="\x02\x04\x10\x10\t\x0e\a\a"
2022/10/21 20:40:41 http2: Framer 0xc0005be000: wrote PING flags=ACK len=8 ping="\x02\x04\x10\x10\t\x0e\a\a"
force call cancel in client
2022/10/21 20:40:41 could not greet: rpc error: code = Canceled desc = context canceled
2022/10/21 20:40:41 http2: Framer 0xc0005be000: wrote RST_STREAM stream=3 len=4 ErrCode=CANCEL
2022/10/21 20:40:44 http2: Framer 0xc0005be000: wrote HEADERS flags=END_HEADERS stream=5 len=7
2022/10/21 20:40:44 http2: Framer 0xc0005be000: wrote DATA flags=END_STREAM stream=5 len=12 data="\x00\x00\x00\x00\a\n\x05world"
2022/10/21 20:40:44 http2: Framer 0xc0005be000: read WINDOW_UPDATE len=4 (conn) incr=12
没有。它关闭网络连接。
由于网络连接已关闭。
好了,本文到此结束,带大家了解了《gRPC 上下文取消传播》,希望本文对你有所帮助!关注编程网公众号,给大家分享更多Golang知识!