restart_interval.go 3.3 KB
Newer Older
“李磊”'s avatar
“李磊” committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
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"))
}