我试图了解 Go 上下文取消在客户端服务通信(例如任何 gRPC API 调用)中是如何工作的。
假设客户端取消了上下文。这是否会导致向服务器发出新的 HTTP 请求,并取消先前/正在进行的 gRPC 请求的上下文?服务器如何知道客户端是否取消了上下文?
默认情况下,HTTP2用作 gPRC 的底层协议。连接上可能有多个流HTTP2。HTTP2这是一张图片,说明了来自网络开发的连接和流
如果您在响应返回之前取消一个 gRPC 调用中的上下文。errCode 可以CANCEL映射到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"})
}
Run Code Online (Sandbox Code Playgroud)
服务器端:延迟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()
}
}
Run Code Online (Sandbox Code Playgroud)
运行代码 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
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5204 次 |
| 最近记录: |