【问题标题】:Context Deadline exceeded for go routine超出 go routine 的上下文截止日期
【发布时间】:2022-12-08 00:52:21
【问题描述】:

使用 Go 例程,我为每个例程设置了最长 30 秒的截止日期,代码如下所示:

func processLibs(ctx context.Context, libs []Library) {
    for _, lib := range libs {
        go processLib(ctx, lib)
    }
}

func processLib(ctx context.Context, lib Library) {
    cancelContext, cancel := context.WithTimeout(ctx, time.Second * 30)
    defer cancel()

    if err := persistLib(ctx, lib); err != nil {
        log.Error("error persisting library", log.Err(err))
    }
}

其中 persistLib 对数据库执行 7 次查询(最大连接数和最大空闲连接数等于 5),并向另一台服务器发出一个请求(传出请求时间正常)。事实上,我知道 libs 的长度小于或等于 100。

我遇到的问题是,有时候,我有一批错误(大约 20% 的 go 例程)说上下文已过期,但我发现真的很奇怪,一个 go 例程只需要 30 秒(测量一下,应该没问题)。

我尝试将 go 例程的数量减少到 70 或 50,但问题仍然存在。我也尝试检查性能改进,但一些 go 例程在第一个查询中间发送截止日期错误,其中一些在 go 例程执行结束时发送,这取决于。

我的数据库是 MySQL 8.0,我使用的是 GO 1.19。

【问题讨论】:

  • “我觉得一个 go 例程只需要 30 秒就很奇怪”为什么这很奇怪?您有 30 秒的超时时间,我希望超时的运行正好需要 30 秒,因为那是它应该停止的地方。
  • 如果 persistLib 函数是一个长时间运行的任务,您可以简单地尝试更长的超时时间。也许将其更改为 60 秒?

标签: mysql go goroutine


【解决方案1】:

真正的问题是你想在这里超时什么交易?或者换句话说,您希望在 30 秒内完成哪些交易? 查看您只需要调用您的代码持久化库作为

persistLib(cancelContext, lib)

这样您将在每个持续操作上等待 30 秒。目前您的代码正在等待中设置的任何秒数CTX在所有持久化操作上。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-07-11
    • 2018-09-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多