feat: 添加时间同步服务和北京时间支持

- 在主程序中集成时间同步服务,每30分钟同步一次时间。
- 在心跳报告中加载并使用北京时间,确保心跳在每分钟的第1秒发送。
- 增强了错误处理,确保在加载时区失败时使用默认时区。
This commit is contained in:
2025-12-24 02:34:05 +08:00
parent bb73e0f384
commit e0d97c4486
3 changed files with 236 additions and 10 deletions

View File

@@ -67,10 +67,11 @@ func GetNodeLocation() (country, province, city, isp string) {
}
type Reporter struct {
cfg *config.Config
client *http.Client
logger *zap.Logger
stopCh chan struct{}
cfg *config.Config
client *http.Client
logger *zap.Logger
stopCh chan struct{}
beijingTZ *time.Location
}
func NewReporter(cfg *config.Config) *Reporter {
@@ -79,32 +80,52 @@ func NewReporter(cfg *config.Config) *Reporter {
// 初始化节点信息(从配置文件读取)
InitNodeInfo(cfg)
// 加载北京时间时区
beijingTZ, err := time.LoadLocation("Asia/Shanghai")
if err != nil {
// 如果加载失败使用UTC+8手动创建
beijingTZ = time.FixedZone("CST", 8*60*60)
logger.Warn("加载时区失败使用UTC+8", zap.Error(err))
}
return &Reporter{
cfg: cfg,
client: &http.Client{
Timeout: 10 * time.Second,
},
logger: logger,
stopCh: make(chan struct{}),
logger: logger,
stopCh: make(chan struct{}),
beijingTZ: beijingTZ,
}
}
func (r *Reporter) Start(ctx context.Context) {
ticker := time.NewTicker(time.Duration(r.cfg.Heartbeat.Interval) * time.Second)
defer ticker.Stop()
// 立即发送一次心跳
r.sendHeartbeat()
for {
// 获取当前北京时间
now := time.Now().In(r.beijingTZ)
// 计算到下一分钟第1秒的时间基于北京时间
nextMinute := now.Truncate(time.Minute).Add(time.Minute)
nextHeartbeatTime := nextMinute.Add(1 * time.Second)
durationUntilNext := nextHeartbeatTime.Sub(now)
// 等待到下一分钟的第1秒
timer := time.NewTimer(durationUntilNext)
select {
case <-ctx.Done():
timer.Stop()
return
case <-r.stopCh:
timer.Stop()
return
case <-ticker.C:
case <-timer.C:
// 在每分钟的第1秒发送心跳北京时间
r.sendHeartbeat()
}
timer.Stop()
}
}