我正在开发一个go应用程序,该应用程序使用gin为其余api提供服务。我的api处理程序函数中有4个调用了一个执行gRPC调用的程序。一个奇怪的事情我看到,所有grpc调用一个处理程序失败与context cancelled
,而其他3成功。
查看日志,我注意到我的API在执行例程之前返回。是否有可能在API返回后,gin取消上下文?
上下文通过几个中间调用从处理程序函数传播到全局例程。
我看到的错误是rpc error: code = Canceled desc = context canceled
我如何调试这个?gin是否在返回响应后取消上下文?
gin是否在返回响应后取消上下文?
Request.Context()
(gin使用http.Request
)的文档说:
对于传入的服务器请求,当客户端连接关闭时上下文被取消,请求被取消(使用HTTP/2),或者当ServeHTTP方法返回时。
所以,是的,当处理程序(实际上是ServeHTTP方法)返回时,上下文关闭(参见这里)。如果连接因其他原因(网络问题,甚至服务器关闭)而断开,则上下文也将被取消。
处理这个问题的正确方法取决于你想要达到什么效果:
- 在许多情况下,正确的行为是在上下文被取消时取消RPC调用。例如,如果您正在检索完成请求所需的信息,那么取消这些请求可能节省资源。
- 如果你触发的调用必须完成,然后传递一个
context.Background()
(或另一个上下文不直接绑定到请求)。
我如何调试这个?
看看为什么你的处理程序在所有RPC调用完成之前返回;如果这是你想要的,那么你将需要使用不同的上下文(但记住,这可能意味着当你实际上还不知道整个过程是否成功时,你将返回一个OK响应代码)。