Files
linkmaster-node/internal/heartbeat/reporter.go
2025-11-21 16:32:35 +08:00

104 lines
2.0 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package heartbeat
import (
"bytes"
"context"
"fmt"
"net"
"net/http"
"time"
"linkmaster-node/internal/config"
"go.uber.org/zap"
)
type Reporter struct {
cfg *config.Config
client *http.Client
logger *zap.Logger
stopCh chan struct{}
}
func NewReporter(cfg *config.Config) *Reporter {
logger, _ := zap.NewProduction()
return &Reporter{
cfg: cfg,
client: &http.Client{
Timeout: 10 * time.Second,
},
logger: logger,
stopCh: make(chan struct{}),
}
}
func (r *Reporter) Start(ctx context.Context) {
ticker := time.NewTicker(time.Duration(r.cfg.Heartbeat.Interval) * time.Second)
defer ticker.Stop()
// 立即发送一次心跳
r.sendHeartbeat()
for {
select {
case <-ctx.Done():
return
case <-r.stopCh:
return
case <-ticker.C:
r.sendHeartbeat()
}
}
}
func (r *Reporter) Stop() {
close(r.stopCh)
}
func (r *Reporter) sendHeartbeat() {
// 获取本机IP
localIP := getLocalIP()
// 发送心跳使用Form格式兼容旧接口
url := fmt.Sprintf("%s/api/node/heartbeat", r.cfg.Backend.URL)
req, err := http.NewRequest("POST", url, bytes.NewBufferString(fmt.Sprintf("realNodeIP=%s&type=pingServer", localIP)))
if err != nil {
r.logger.Error("创建心跳请求失败", zap.Error(err))
return
}
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
resp, err := r.client.Do(req)
if err != nil {
r.logger.Warn("发送心跳失败", zap.Error(err))
return
}
defer resp.Body.Close()
if resp.StatusCode == http.StatusOK {
r.logger.Debug("心跳发送成功", zap.String("ip", localIP))
} else {
r.logger.Warn("心跳发送失败", zap.Int("status", resp.StatusCode))
}
}
func getLocalIP() string {
// 获取第一个非回环IP
addrs, err := net.InterfaceAddrs()
if err != nil {
return "127.0.0.1"
}
for _, addr := range addrs {
if ipNet, ok := addr.(*net.IPNet); ok && !ipNet.IP.IsLoopback() {
if ipNet.IP.To4() != nil {
return ipNet.IP.String()
}
}
}
return "127.0.0.1"
}