【问题标题】:Handling Context Cancelled errors处理上下文取消错误
【发布时间】:2020-10-04 10:37:09
【问题描述】:

我是Go 的新手,并且每天都在学习它。我在我们的项目中看到很多context cancelled 错误,这让我很恼火。所以我想深入挖掘一下,弄清楚发生了什么。

如果我没记错的话,用“简单”的术语来说,上下文取消意味着给定的请求(通过使用 gokit 的 grpc)已经超时。正确的?如果是这样,解决此问题的最佳方法应该是什么?

  1. 我是否应该调查这些请求超时的原因(可能底层数据库查询需要很长时间或其他什么)并解决这些问题?

  2. Go 内部是否暗示了与Go 相关的某些内容?

  3. 开始处理此错误的最佳方法是什么?现在,我看到的都是“上下文已取消”,不知道为什么会这样。

【问题讨论】:

  • "上下文取消意味着给定的请求已经超时,对吗?"没有。超时产生context.DeadlineExceeded。 Canceled 表示其中一个 CancelFuncs 已被调用,仅此而已。

标签: go grpc grpc-go


【解决方案1】:

上下文定义了 Context 类型,它携带跨越 API 边界和进程之间的截止日期、取消信号和其他请求范围的值。

对服务器的传入请求应该创建一个上下文,而对服务器的传出调用应该接受一个上下文。

上下文取消错误不一定意味着超时错误。

场景 1:

如果你正在使用 goroutine,如果父 goroutine 完成但子 goroutine 仍然在后台运行,并且子 goroutine 有一个父 goroutine 通用的上下文,这可能会在上下文被取消时结束,如果父 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)

【讨论】:

    猜你喜欢
    • 2012-10-13
    • 1970-01-01
    • 2017-04-16
    • 1970-01-01
    • 2021-07-30
    • 1970-01-01
    • 2016-07-11
    • 2017-01-09
    • 2015-06-09
    相关资源
    最近更新 更多