package monitor_daemon import ( "fmt" "time" ) // 用途: 当前文件用来控制进程重启的间隔时间 // 同时满足如下条件则不重启: // 1. 设置了最大间隔时间 // 2. 距离上次重启小于累增的间隔 const ( DefaultIncrInterval = 20 * time.Second // 建议值: 每次重启累增的时间间隔 DefaultMaxInterval = 20 * time.Minute // 建议值: 重启累增时间间隔的最大值,增到这个值后平稳重启,不再累增 ) // 管理重启时间间隔 type restartInterval struct { config *restartIntervalConfig // 重启时间间隔的配置 state *restartIntervalState // 重启时间间隔的状态 } // 固定的配置 type restartIntervalConfig struct { maxInterval time.Duration // 防止持续重启,加上递增逻辑,重启间隔可以递增到当前最大值,不设置则按照默认interval进行重启 incr time.Duration // 每次累增的间隔 stableDura time.Duration // 运行的时间间隔大于该值认为是稳定的,可以重置重累增的间隔,防止因为偶发问题无法及时拉起 } // 变化的状态 type restartIntervalState struct { lastStart time.Time // 上次重启时间 curInterval time.Duration // 累增后的时间间隔 } func newRestartInterval() *restartInterval { return &restartInterval{ config: &restartIntervalConfig{ maxInterval: 0, incr: 0, }, state: &restartIntervalState{ curInterval: 0, lastStart: time.Now(), }, } } func (r *restartInterval) setMaxInterval(maxInterval time.Duration) { if maxInterval == 0 { return } r.config.maxInterval = maxInterval r.config.stableDura = 2 * maxInterval // 2倍只是一个大约数 } func (r *restartInterval) setIncr(incr time.Duration) { r.config.incr = incr } // setLastStart 需要设置: 1.上次启动时间; 2.下次启动要求的时间间隔累增; func (r *restartInterval) setLastStart() { if r.config.maxInterval == 0 { return } // 设置本次启动的时间 defer func() { r.state.lastStart = time.Now() }() // 已经稳定运行了一段时间后的重启,将重启间隔重置为类似第一次启动 if r.state.lastStart.Add(r.config.stableDura).Before(time.Now()) { r.state.curInterval = r.config.incr return } // 已经添加到最大值了,不再添加了 if r.state.curInterval == r.config.maxInterval { return } // 递增重启间隔后如果小于最大间隔,则递增,否则采用最大间隔 if r.state.curInterval+r.config.incr < r.config.maxInterval { r.state.curInterval = r.state.curInterval + r.config.incr } else { r.state.curInterval = r.config.maxInterval } } func (r *restartInterval) isNeedStart() bool { // 未启用每次重启加大时间间隔的特性 if r.config.maxInterval == 0 { return true } // 达到时间要求的时间间隔,则可以重启 if r.state.lastStart.Add(r.state.curInterval).Before(time.Now()) { return true } return false } func (r *restartInterval) GetLastStart() time.Time { return r.state.lastStart } func (r *restartInterval) GetCurInterval() time.Duration { return r.state.curInterval } func (r *restartInterval) String() string { return fmt.Sprintf("config: maxInterval=%s incr=%s state: curInterval=%s lastStart:%s", r.config.maxInterval, r.config.incr, r.state.curInterval, r.state.lastStart.Format("2006-01-02 15:04:05")) }