我有一个Prometheus服务器,其数据库包含一些指标。我需要一个从数据库中获取这些指标并将其每分钟循环发送到另一台服务器的过程。我从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
我认为原因是传递给Query API的上下文的截止日期已过期。解决此问题的方法是在循环中仅移动以下两行:
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
我已验证它可以工作,现在它可以每分钟发送一次指标,但是我不确定此修复程序能否长期正常运行。我担心取消功能应该以不同的方式进行管理,以正确释放资源,最终没有必要在每个循环中创建上下文,而只是延长期限。
有人知道我可以正确修复我的代码,以避免可能的内存泄漏或其他潜在的未来问题吗?
答案 0 :(得分:1)
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
所有请求使用此上下文的总时间为10秒;您应该将其移入for循环,以便每个请求可以拥有10秒的上下文
理想情况下,您不希望此延迟继续进行;所以你可以