gRPC(Go)教程(八)---使用context进行超时控制
本文主要记录了如何使用 context 为 RPC 请求设置超时时间,或者通过 cancel 手动取消本次请求。
1. 概述
gRPC 系列相关代码见 Github
通过 ctx 完成 cancel 和 deadline 功能。
Go 语言中可以通过 ctx 来控制各个 Goroutine,调用 cancel 函数,则该 ctx 上的各个子 Goroutine 都会被一并取消。
gRPC 中同样实现了该功能,在调用方法的时候可以传入 ctx 参数。
gRPC 会通过 HTTP2 HEADERS Frame 来传递相关信息。
2. deadline
gRPC 提倡TL;DR: Always set a deadline
Deadlines 允许gRPC 客户端设置自己等待多长时间来完成 RPC 操作,直到出现这个错误 DEADLINE_EXCEEDED
。但是在正常情况下默认设置是一个很大的数值。
如果不设置截止日期时,如果出现阻塞,那么所有的请求可能在最大请求时间过后才超时,最终可能导致资源被耗尽。
由于类似的问题,在高并发的时候导致了一次事故,具体看数据库连接池该设置多大?记一次由连接池引发的事故
Server
如果客户端传来的消息时 delay 则 sleep 两秒,如果是带[propagate me]
前缀的消息则由服务端在延迟 800ms 后发起一次 RPC 调用。
|
|
Client
客户端则是为每次 RPC 调用都指定超时时间为 1秒。
|
|
Run
|
|
|
|
其中请求 2 是传递的 delay 消息服务端会 sleep 两秒,所以触发 deadline,请求4和6 由于有两个[propagate me]
前缀,所以会传递两轮,每次 sleep 800ms,再第二轮的时候也会触发 deadline。
请求1为正常请求,请求3和5只传递一轮,只 sleep 800ms 所以没有触发 deadline。
3. cancel
除了等待 deadline 超时之外,客户端还可以主动调用 cancel 取消本次请求。
比如在某次调用中,客户端某个环节报错导致本次请求已经可以直接返回了,这时候在等待服务端返回已经没有意义了。此时就可以直接调用 cancel 取消本次请求,而不是让服务端一直等待到超时才返回。
Server
|
|
Client
|
|
4. 小结
不管是 cancel 和 deadline 都只需调用方传递对应的 ctx 即可。gRPC 中已经做了对应的实现,所以使用起来和在 Goroutine 中传递 ctx 没有太大的区别。
ctx 可以使用context.WithDeadline()
或者context.WithTimeout()
,二者效果类似,只是传递的参数不一样。
timeout 只能设置在某一段时间后超时,比如3秒后超时,deadline 则可以设置到具体某个时间点,比如在8点10分20秒的时候返回。类似于 Redis 中的 Expire 和 ExpireAt。
gRPC 系列相关代码见 Github
5. 参考
https://github.com/grpc/grpc-go
https://blog.csdn.net/u014229282/article/details/109294837
https://grpc.io/blog/deadlines/
- 原文作者:意琦行
- 原文链接:https://www.lixueduan.com/post/grpc/08-ctx-cancel-deadline/
- 版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可,非商业转载请注明出处(作者,原文链接),商业转载请联系作者获得授权。