Prometheus go客户端错误上下文截止日期已超过



我有一台Prometheus服务器,它有一个包含一些度量的数据库。我需要一个过程,从数据库中获取这些度量,并每分钟循环将它们发送到另一台服务器。我以普罗米修斯为例编写了以下代码:

client, err := api.NewClient(api.Config{Address: "http://localhost:9090",})
if err != nil {
log.Error(err)
os.Exit(1)
}
v1api := v1.NewAPI(client)
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
for { //main loop
if result, warnings, err := v1api.Query(ctx, "patroni_patroni_info", time.Now().Add(-1 * time.Minute)); err != nil {
log.Error(err)
} else {
if len(warnings) > 0 {
log.Warning(warnings)
}
if err = sendMetricToAnotherServer(result); err != nil {
log.Error(err)
}
}
log.Debugf("main sleeping %ds...", opts.ServersRefreshLoopSeconds)
time.Sleep(time.Second * time.Duration(opts.ServersRefreshLoopSeconds))
}

现在第一次发送工作正常,但从第二次发送开始,我出现了以下错误。

2020/11/10 09:56:36 ERROR main: Post http://localhost:9090/api/v1/query: context deadline exceeded

我认为原因是传递给Queryneneneba API的上下文的截止日期已过期。解决这个问题的方法是简单地在循环中移动以下两行:

ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()

我验证了它的有效性,现在它可以每分钟发送一次指标,但我不确定这个修复程序是否能长期正常运行。我担心cancel函数应该以不同的方式进行管理,以正确地释放资源,最终不必在每个循环中创建上下文,而只需扩展截止日期。

有人知道我可以正确地修复代码以避免可能的内存泄漏或其他潜在的未来问题吗?

ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()

此上下文是所有请求总共使用的10秒;您应该将其移动到for循环内部,这样每个请求都可以有10秒的上下文。

理想情况下,您不希望这种延迟继续堆积;所以你可以选择

  1. 将其移动到另一个函数(或创建一个内联函数并调用它(这可以确保defer函数每次都被调用,并且不会被堆叠
  2. 在循环结束时手动调用cancel函数

最新更新