prometheus的sdk client_golang 使用 定时器
之前线上监控的agent都是直接 time.Sleep(time.Duration(collectInterval) * time.Second) ,多少有些许的low,每次开始采集数据的时间都是从程序开始执行就开始采集,很显然这种偷懒的方式是不合理的。
1、简单复制粘贴一下
func AbNormalLoglistener(collectInterval int) { abnormal_loglistener_Gauge := prometheus.NewGaugeVec( prometheus.GaugeOpts{ Namespace: "tc", Subsystem: "serverMetricExtend", Name: "abnormal_loglistener_log", Help: "Loglistener An exception exists in the log file.", }, []string{ "hostname", "alert_name", }, ) prometheus.MustRegister(abnormal_loglistener_Gauge) _t := tools.Server{} sname := _t.GetServerHostName() go func() { defer func() { if r := recover(); r != nil { metricLog.Error(r) } }() ticker := time.NewTicker(time.Duration(collectInterval) * time.Second) now := time.Now() nextMinute := now.Truncate(time.Duration(collectInterval) * time.Second).Add(time.Duration(collectInterval) * time.Second) waitTime := nextMinute.Sub(now) time.Sleep(waitTime) for { metricsBack := _t.FetchDirModTime() for alert_name, status := range metricsBack{ abnormal_loglistener_Gauge.With(prometheus.Labels{"hostname": sname, "alert_name": alert_name}).Set(float64(status)) } <-ticker.C nextMinute = nextMinute.Add(time.Duration(collectInterval) * time.Second) waitTime = nextMinute.Sub(time.Now()) time.Sleep(waitTime) } }() }
2、方式一 time.Ticker
package main import ( "fmt" "time" ) func main() { // 创建一个定时器,每隔一分钟触发一次 ticker := time.NewTicker(time.Minute) // 获取当前时间 now := time.Now() // 计算下一分钟的开始时间 nextMinute := now.Truncate(time.Minute).Add(time.Minute) // 计算需要等待的时间 waitTime := nextMinute.Sub(now) // 等待到下一分钟的开始时间 time.Sleep(waitTime) // 使用一个无限循环来控制方法的执行 for { // 执行你的方法 fmt.Println("执行方法") // 等待定时器的下一次触发事件 <-ticker.C // 计算下一分钟的开始时间 nextMinute = nextMinute.Add(time.Minute) // 计算需要等待的时间 waitTime = nextMinute.Sub(time.Now()) // 等待到下一分钟的开始时间 time.Sleep(waitTime) } }
3、方式二 time.Timer
package main import ( "fmt" "time" ) func main() { // 获取当前时间 now := time.Now() // 计算下一分钟的开始时间 nextMinute := now.Truncate(time.Minute).Add(time.Minute) // 计算需要等待的时间 waitTime := nextMinute.Sub(now) // 创建一个定时器,在等待时间结束后执行任务 timer := time.NewTimer(waitTime) // 使用一个无限循环来控制协程的执行 for { <-timer.C // 等待定时器的触发事件 // 执行你的协程任务 go func() { fmt.Println("执行协程任务") // 在这里编写你的协程任务逻辑 }() // 计算下一分钟的开始时间 nextMinute = nextMinute.Add(time.Minute) // 重新计算需要等待的时间 waitTime = nextMinute.Sub(time.Now()) // 重置定时器 timer.Reset(waitTime) } }
4、这两种方式的区别,gpt给的答案,请各位自行斟酌
-
time.NewTimer
:time.NewTimer
创建一个单次触发的定时器,它在指定的时间间隔过后触发一次。- 适用于需要在指定时间间隔后执行一次操作的场景。
- 可以使用
timer.Reset
方法重新设置定时器的触发时间。
-
time.NewTicker
:time.NewTicker
创建一个重复触发的定时器,它会以固定的时间间隔重复触发。- 适用于需要定期执行某个操作的场景,比如每隔一段时间执行一次任务。
- 每次触发时,
time.Ticker
类型的值会发送一个时间到其内部的通道C
,你可以使用<-ticker.C
来等待触发事件。 - 可以使用
ticker.Stop
方法停止定时器的触发。
5、一些点的解惑
m := time.Now().Truncate(time.Minute) fmt.Printf("m:%s\n",m ) s := time.Now().Truncate(time.Duration(3600) * time.Second) fmt.Printf("s:%s\n",s )
执行返回结果,自行感受,time.Now().Truncate():
m:2023-08-08 11:56:00 +0800 CST
s:2023-08-08 11:00:00 +0800 CST
6、文章仅个人记录,要想深入请自行分析源码。