Przeglądaj źródła

优化netmgrd模块,加入http(tcp)从大数据平台同步网络时间,失败时再使用ntp时间兜底

niujiuru 1 tydzień temu
rodzic
commit
8c3bf411a9

+ 18 - 12
netmgrd/netmgrd.go

@@ -77,32 +77,38 @@ func serviceRun() {
 			}
 
 			// 3.2, 联网检测-看结果
-			dnsOK, pingOK, tcpOK, httpOK := CheckNetwork()
+			dnsOK, pingOK, tcpOK, httpOK, httpTime := CheckNetwork()
 			baseapp.Logger.Infof("[%s] 联网类型: %s; 检测结果: DNS OK=%v, PING OK=%v, TCP OK=%v, HTTP OK=%v", MODULE_NAME, curNetType.String(), dnsOK, pingOK, tcpOK, httpOK)
 
 			// 3.3, 联网成功-在线时
-			if dnsOK && pingOK && tcpOK {
+			netOK := tcpOK || pingOK
+			if netOK {
 				isOnline.Store(true)
 				offlineStartTs.Store(0)
 
-				if isSyncNTPTimeOK.Load() {
-					if time.Since(lastSyncNTPTime) >= (time.Duration(60) * time.Minute) { // 1小时后需要再次同步NTP时间
-						isSyncNTPTimeOK.Store(false)
-					} else {
-						t.Reset(interval2)
-						continue
-					}
+				if isSyncNTPTimeOK.Load() && time.Since(lastSyncNTPTime) < (time.Duration(60)*time.Minute) {
+					t.Reset(interval2)
+					continue
+				}
+
+				var err error
+				if !httpTime.IsZero() { // 优先使用HTTP时间, 实测速度快且精度高
+					err = SetSystemTime(httpTime)
+				}
+
+				if err != nil {
+					err = SyncNTPTime() //// 同步HTTP时间失败, 则尝试同步标准时间
 				}
 
-				err := SyncNTPTime()
 				if err == nil {
 					isSyncNTPTimeOK.Store(true)
-					baseapp.Logger.Infof("[%s] NTP时间已同步", MODULE_NAME)
+					baseapp.Logger.Infof("[%s] ✅ 系统时间已同步: %s", MODULE_NAME, time.Now().Format("2006-01-02 15:04:05"))
 					lastSyncNTPTime = time.Now()
 					t.Reset(interval2)
 					continue
 				} else {
-					baseapp.Logger.Errorf("[%s] 同步NTP时间时有错误发生: %v!!", MODULE_NAME, err)
+					isSyncNTPTimeOK.Store(false)
+					baseapp.Logger.Errorf("[%s] 同步系统时间时有错误发生: %v!!", MODULE_NAME, err)
 					t.Reset(interval1)
 					continue
 				}

+ 27 - 26
netmgrd/ntp.go

@@ -2,6 +2,7 @@ package netmgrd
 
 import (
 	"fmt"
+	"math"
 	"os/exec"
 	"sync"
 	"time"
@@ -16,9 +17,9 @@ var servers = []string{
 }
 
 type ntpResult struct {
-	t       time.Time
-	stratum uint8
-	err     error
+	t   time.Time
+	d   time.Duration
+	err error
 }
 
 func SyncNTPTime() error {
@@ -40,12 +41,21 @@ func getAccurateTime(servers []string, timeout time.Duration) (time.Time, error)
 	for _, s := range servers {
 		go func(s string) {
 			defer wg.Done()
+
 			resp, err := ntp.QueryWithOptions(s, ntp.QueryOptions{Timeout: timeout})
-			if err != nil || resp.Stratum == 0 || resp.Stratum > 5 || resp.Time.IsZero() {
-				ch <- ntpResult{err: err} // "resp.Stratum"为0(无效服务器)或大于5(精度较低)
+			if err != nil {
+				ch <- ntpResult{err: err}
 				return
 			}
-			ch <- ntpResult{t: resp.Time, stratum: resp.Stratum}
+
+			if resp.Stratum == 0 || resp.Time.IsZero() {
+				ch <- ntpResult{err: fmt.Errorf("invalid ntp response")}
+				return
+			}
+
+			t := resp.Time.Add(resp.RTT / 2)
+			d := resp.RootDistance // 最大可能偏差
+			ch <- ntpResult{t: t, d: d, err: nil}
 		}(s)
 	}
 
@@ -54,34 +64,25 @@ func getAccurateTime(servers []string, timeout time.Duration) (time.Time, error)
 		close(ch)
 	}()
 
-	var results []ntpResult
+	var bestTime time.Time
+	var bestDist time.Duration = math.MaxInt64
+
 	for r := range ch {
-		if r.err == nil {
-			results = append(results, r)
+		if r.err != nil {
+			continue
 		}
-	}
 
-	if len(results) == 0 {
-		return time.Time{}, fmt.Errorf("所有NTP服务器请求失败或无有效时间")
-	}
-
-	// 找最低 Stratum
-	minStratum := uint8(255)
-	for _, r := range results {
-		if r.stratum < minStratum {
-			minStratum = r.stratum
+		if r.d < bestDist {
+			bestDist = r.d
+			bestTime = r.t
 		}
 	}
 
-	// 最低 Stratum 的时间
-	var bestTimes []time.Time
-	for _, r := range results {
-		if r.stratum == minStratum {
-			bestTimes = append(bestTimes, r.t)
-		}
+	if bestTime.IsZero() {
+		return time.Time{}, fmt.Errorf("no valid ntp response")
 	}
 
-	return bestTimes[0], nil
+	return bestTime, nil
 }
 
 var setTimeMu sync.Mutex // 保证调用 SetSystemTime() 函数的线程安全

+ 19 - 7
netmgrd/ping.go

@@ -13,7 +13,7 @@ const (
 	///////////////////////////////////////
 	// 白名单联网检测地址
 	TEST_URL1 = "www.aliyun.com"
-	TEST_URL2 = "http://www.aliyun.com"
+	TEST_URL2 = "http://8.136.98.49"
 	TEST_HOST = "223.5.5.5" // 阿里云DNS主机
 	///////////////////////////////////////
 	TEST_TIMEOUT = 5 * time.Second
@@ -50,25 +50,37 @@ func test3() bool {
 	return true
 }
 
-func test4() bool { // HTTP访问测试(不跟随重定向)
+func test4() (bool, time.Time) { // HTTP访问测试(不跟随重定向)
 	client := http.Client{
 		Timeout: TEST_TIMEOUT,
 		CheckRedirect: func(req *http.Request, via []*http.Request) error {
 			return http.ErrUseLastResponse
 		},
 	}
+
 	resp, err := client.Head(TEST_URL2)
 	if err != nil {
-		return false
+		return false, time.Time{}
 	}
 	defer resp.Body.Close()
-	return true
+
+	date := resp.Header.Get("Date")
+	if date == "" {
+		return true, time.Time{}
+	}
+
+	t, err := time.Parse(http.TimeFormat, date)
+	if err != nil {
+		return true, time.Time{}
+	}
+
+	return true, t
 }
 
-func CheckNetwork() (dnsOK, pingOK, tcpOK, httpOK bool) {
+func CheckNetwork() (dnsOK, pingOK, tcpOK, httpOK bool, httpTime time.Time) {
 	bOK1 := test1()
 	bOK3 := test3()
-	bOK4 := test4()
+	bOK4, httpDate := test4()
 	bOK2 := bOK3 || bOK4 || test2()
-	return bOK1, bOK2, bOK3, bOK4
+	return bOK1, bOK2, bOK3, bOK4, httpDate
 }

BIN
package/rtu_linux_modules_1.0.0.1.tar.gz


BIN
package/yfkj_ssh_client_1.0.0.1.tar.gz