我是Go
新手,并且仍然每天学习它。我在我们的项目中看到很多context cancelled
错误,这让我有点烦恼。所以我想更深入地挖掘一下,弄清楚发生了什么。
如果我没记错的话,用"简单"的术语来说,上下文取消意味着给定的请求(通过 grpc 使用 gokit(已经超时。正确?如果是这样,解决此问题的最佳方法是什么?
-
我应该调查为什么这些请求超时(可能是底层数据库查询需要很长时间或其他时间(并解决这些问题吗?
-
是不是内部
Go
暗示与Go
有关的事情? -
开始处理此错误的最佳方法是什么?现在,我看到的只是"上下文取消",不知道为什么会这样。
上下文定义上下文类型,该类型跨 API 边界和进程之间携带截止时间、取消信号和其他请求范围的值。
对服务器的传入请求应创建上下文,对服务器的传出调用应接受上下文。
上下文取消错误并不一定意味着超时错误。
场景 1:
如果您使用的是 go 例程,如果父 go 例程完成,但子例程仍在后台运行,并且子 go 例程具有父 go 例程通用的上下文,则如果父 go 例程在退出之前关闭上下文,则最终可能会在上下文中取消。
因此,如果子例程不依赖于父例程上下文,则始终为后台 go 例程创建新上下文是一种很好的做法。可以使用context.Background()
创建新上下文
场景 2:
如果应用程序基于微服务(或有多个使用上下文相互调用的组件(,如果微服务 1 调用微服务 2,微服务 2 优先关闭或取消上下文,即使在这种情况下,也可能收到此错误。
可以通过调用cancel()
函数来关闭上下文,如下所示:
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
defer cancel()
取消此上下文会释放与其关联的资源。因此,如果被调用方已显式关闭上下文(如上所示(,则可能会导致调用方出现上下文取消错误。
可以处理这些上下文消除错误,检查来自grpc.Dial()
调用的context.Canceled
错误(如果您使用的是 grpc(