@@ -13,7 +13,6 @@ type TrafficScheduler struct {
1313 db * gorm.DB
1414 trafficService * TrafficService
1515 cleanupService * CleanupService
16- ticker * time.Ticker
1716 ctx context.Context
1817 cancel context.CancelFunc
1918}
@@ -35,32 +34,51 @@ func NewTrafficScheduler(db *gorm.DB) *TrafficScheduler {
3534func (s * TrafficScheduler ) Start () {
3635 log .Println ("[流量调度器] 启动定时任务..." )
3736
38- // 每小时执行一次数据聚合
39- s .ticker = time .NewTicker (1 * time .Hour )
40-
4137 // 立即执行一次初始化,汇总最近24小时的数据
4238 go func () {
39+ // 启动后稍作延迟,减少与 SSE 初始写入的锁竞争
40+ time .Sleep (10 * time .Second )
41+
4342 log .Println ("[流量调度器] 开始初始化最近24小时流量汇总数据..." )
4443 start := time .Now ()
4544
46- if err := s .trafficService .InitializeRecentTrafficData (); err != nil {
47- log .Printf ("[流量调度器] 初始化24小时汇总数据失败: %v" , err )
45+ // 对 SQLite locked 做有限重试
46+ var err error
47+ for attempt := 1 ; attempt <= 5 ; attempt ++ {
48+ err = s .trafficService .InitializeRecentTrafficData ()
49+ if err == nil {
50+ break
51+ }
52+ log .Printf ("[流量调度器] 初始化24小时汇总数据失败(第%d次): %v" , attempt , err )
53+ time .Sleep (time .Duration (attempt ) * 2 * time .Second )
54+ }
55+
56+ if err != nil {
57+ log .Printf ("[流量调度器] 初始化24小时汇总数据最终失败: %v" , err )
4858 } else {
4959 duration := time .Since (start )
5060 log .Printf ("[流量调度器] 初始化24小时汇总数据完成,耗时: %v" , duration )
5161 }
5262
5363 // 然后执行上一小时的常规聚合(如果有遗漏)
5464 log .Println ("[流量调度器] 执行启动时常规数据聚合..." )
55- if err := s .trafficService .AggregateTrafficData (); err != nil {
56- log .Printf ("[流量调度器] 启动时常规数据聚合失败: %v" , err )
65+ for attempt := 1 ; attempt <= 5 ; attempt ++ {
66+ err = s .trafficService .AggregateTrafficData ()
67+ if err == nil {
68+ break
69+ }
70+ log .Printf ("[流量调度器] 启动时常规数据聚合失败(第%d次): %v" , attempt , err )
71+ time .Sleep (time .Duration (attempt ) * 2 * time .Second )
72+ }
73+ if err != nil {
74+ log .Printf ("[流量调度器] 启动时常规数据聚合最终失败: %v" , err )
5775 } else {
5876 log .Println ("[流量调度器] 启动时常规数据聚合完成" )
5977 }
6078 }()
6179
6280 // 启动定时任务
63- go s .run ()
81+ go s .runAligned ()
6482
6583 // 启动数据清理任务(每天凌晨3点执行)
6684 go s .runCleanupTask ()
@@ -72,22 +90,28 @@ func (s *TrafficScheduler) Start() {
7290func (s * TrafficScheduler ) Stop () {
7391 log .Println ("[流量调度器] 停止定时任务..." )
7492
75- if s .ticker != nil {
76- s .ticker .Stop ()
77- }
78-
7993 s .cancel ()
8094 log .Println ("[流量调度器] 定时任务已停止" )
8195}
8296
83- // run 运行主要的聚合任务
84- func (s * TrafficScheduler ) run () {
97+ // runAligned 在每个整点后延迟一小段时间执行聚合,减少与分钟写入尖峰的冲突
98+ func (s * TrafficScheduler ) runAligned () {
99+ const delayAfterHour = 2 * time .Minute
100+
101+ now := time .Now ()
102+ nextRun := now .Truncate (time .Hour ).Add (1 * time .Hour ).Add (delayAfterHour )
103+ timer := time .NewTimer (time .Until (nextRun ))
104+ defer timer .Stop ()
105+
85106 for {
86107 select {
87108 case <- s .ctx .Done ():
88109 return
89- case <- s . ticker .C :
110+ case <- timer .C :
90111 s .executeAggregation ()
112+
113+ nextRun = nextRun .Add (1 * time .Hour )
114+ timer .Reset (time .Until (nextRun ))
91115 }
92116 }
93117}
0 commit comments