From 917df01342cd81a9e1ffeabee02748a8332edd1f Mon Sep 17 00:00:00 2001 From: Akizon77 Date: Sat, 1 Nov 2025 15:46:57 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=BC=98=E5=8C=96=20goroutine=20?= =?UTF-8?q?=E5=90=AF=E5=8A=A8=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cmd/root.go | 12 ++++++ monitoring/netstatic/static.go | 72 ++++++++++++++++++++-------------- 2 files changed, 55 insertions(+), 29 deletions(-) diff --git a/cmd/root.go b/cmd/root.go index c27b04a..b0f6e31 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -1,10 +1,13 @@ package cmd import ( + "context" "crypto/tls" "log" "net/http" "os" + "os/signal" + "syscall" "github.com/komari-monitor/komari-agent/cmd/flags" "github.com/komari-monitor/komari-agent/dnsresolver" @@ -20,6 +23,15 @@ var RootCmd = &cobra.Command{ Short: "komari agent", Long: `komari agent`, Run: func(cmd *cobra.Command, args []string) { + // 捕获中止信号,优雅退出 + stopCtx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM) + defer stop() + go func() { + <-stopCtx.Done() + log.Printf("shutting down gracefully...") + netstatic.Stop() + os.Exit(0) + }() if flags.ShowWarning { ShowToast() diff --git a/monitoring/netstatic/static.go b/monitoring/netstatic/static.go index a9a189a..92fdfbb 100644 --- a/monitoring/netstatic/static.go +++ b/monitoring/netstatic/static.go @@ -245,6 +245,39 @@ func flushCacheLocked(ts uint64) { staticCache = make(map[string][]TrafficData) } +// startGoroutinesLocked 启动采集和保存的 goroutines(调用前必须已持有锁) +func startGoroutinesLocked() { + // 采集 goroutine + go func() { + for { + select { + case <-detectTicker.C: + mu.Lock() + sampleOnceLocked() + mu.Unlock() + case <-stopCh: + return + } + } + }() + + // 保存 goroutine + go func() { + for { + select { + case t := <-saveTicker.C: + mu.Lock() + flushCacheLocked(uint64(t.Unix())) + purgeExpiredLocked() + _ = saveToFileLocked() + mu.Unlock() + case <-stopCh: + return + } + } + }() +} + // GetNetStatic 获取当前的所有流量统计数据 func GetNetStatic() (*NetStatic, error) { mu.RLock() @@ -281,35 +314,8 @@ func StartOrContinue() error { stopCh = make(chan struct{}) running = true - // 采集 goroutine - go func() { - for { - select { - case <-detectTicker.C: - mu.Lock() - sampleOnceLocked() - mu.Unlock() - case <-stopCh: - return - } - } - }() - - // 保存 goroutine - go func() { - for { - select { - case t := <-saveTicker.C: - mu.Lock() - flushCacheLocked(uint64(t.Unix())) - purgeExpiredLocked() - _ = saveToFileLocked() - mu.Unlock() - case <-stopCh: - return - } - } - }() + // 启动 goroutines + startGoroutinesLocked() return nil } @@ -476,14 +482,22 @@ func SetNewConfig(newCfg NetStaticConfig) error { config = cfg // 重新配置 ticker(若运行中) if running { + // 先停止旧的 ticker 和 goroutines if detectTicker != nil { detectTicker.Stop() } if saveTicker != nil { saveTicker.Stop() } + close(stopCh) + + // 重新创建 ticker 和 channel detectTicker = time.NewTicker(time.Duration(cfg.DetectInterval * float64(time.Second))) saveTicker = time.NewTicker(time.Duration(cfg.SaveInterval * float64(time.Second))) + stopCh = make(chan struct{}) + + // 重新启动 goroutines + startGoroutinesLocked() // 当配置了指定网卡白名单时,清理不在白名单内的缓存与上次计数,避免无用数据积累 if len(cfg.Nics) > 0 {