瀏覽代碼

测速功能优化,新增重测功能

Taio_O 1 周之前
父節點
當前提交
24706f2f54
共有 8 個文件被更改,包括 152 次插入16 次删除
  1. 1 1
      env.example
  2. 47 0
      go-speed-test/internal/core/scheduler.go
  3. 2 1
      public/app.js
  4. 8 0
      public/index.html
  5. 46 2
      src/api/routes.js
  6. 47 10
      src/core/scheduler.js
  7. 0 1
      src/core/speedTester.js
  8. 1 1
      src/utils/logger.js

+ 1 - 1
env.example

@@ -19,7 +19,7 @@ CLASH_API_URL=http://127.0.0.1:9090
 CLASH_SUBSCRIPTION_URL=http://so.xfxssr.me/api/v1/client/subscribe?token=7854d59f38ac51700730b9e782c5160c
 
 # 测速配置
-SPEED_TEST_INTERVAL=5 # 分钟
+SPEED_TEST_INTERVAL=10 # 分钟
 SPEED_TEST_TIMEOUT=10000 # 毫秒
 SPEED_TEST_URLS=https://www.google.com,https://www.youtube.com,https://www.github.com
 

+ 47 - 0
go-speed-test/internal/core/scheduler.go

@@ -117,6 +117,52 @@ func (s *Scheduler) runSpeedTest() {
 	// 执行测速
 	results := s.speedTester.TestNodes(nodes)
 
+	// 检查是否有高延迟节点需要重测
+	var highLatencyNodes []database.Node
+	var highLatencyResults []*database.TestResult
+	
+	for i, result := range results {
+		if result.IsSuccess && result.Latency != nil && *result.Latency > 2000 {
+			highLatencyNodes = append(highLatencyNodes, nodes[i])
+			highLatencyResults = append(highLatencyResults, result)
+		}
+	}
+
+	// 如果有高延迟节点,进行重测
+	if len(highLatencyNodes) > 0 {
+		logger.Info("发现高延迟节点,开始重测", map[string]interface{}{
+			"high_latency_count": len(highLatencyNodes),
+		})
+		
+		// 重测高延迟节点
+		retestResults := s.speedTester.TestNodes(highLatencyNodes)
+		
+		// 更新测试结果,使用重测的结果
+		for i, node := range highLatencyNodes {
+			retestResult := retestResults[i]
+			// 找到原始结果在results中的索引
+			for j, originalResult := range results {
+				if originalResult.NodeID == node.ID {
+					// 如果重测结果更好,使用重测结果
+					if retestResult.IsSuccess && retestResult.Latency != nil && *retestResult.Latency <= 2000 {
+						results[j] = retestResult
+						logger.Info("节点重测成功", map[string]interface{}{
+							"node_name": node.Name,
+							"original_latency": *highLatencyResults[i].Latency,
+							"new_latency": *retestResult.Latency,
+						})
+					} else {
+						logger.Info("节点重测后仍为高延迟", map[string]interface{}{
+							"node_name": node.Name,
+							"latency": retestResult.Latency,
+						})
+					}
+					break
+				}
+			}
+		}
+	}
+
 	// 处理测试结果并更新节点状态
 	s.processTestResults(nodes, results)
 
@@ -135,6 +181,7 @@ func (s *Scheduler) runSpeedTest() {
 		"total":   len(results),
 		"success": successCount,
 		"failed":  failCount,
+		"retested": len(highLatencyNodes),
 	})
 }
 

+ 2 - 1
public/app.js

@@ -546,7 +546,8 @@ async function startSpeedTest() {
         const data = await response.json();
         
         if (data.success) {
-            showSuccess(`测速已开始,共测试 ${data.data.testedNodes} 个节点`);
+            const retestedInfo = data.data.retestedNodes > 0 ? `,其中 ${data.data.retestedNodes} 个高延迟节点已重测` : '';
+            showSuccess(`测速已开始,共测试 ${data.data.testedNodes} 个节点${retestedInfo}`);
             // 刷新当前页面数据
             if (currentPage === 'dashboard') {
                 await loadDashboard();

+ 8 - 0
public/index.html

@@ -161,6 +161,14 @@
                                     </button>
                                 </div>
                             </div>
+                            <div class="row mt-3">
+                                <div class="col-12">
+                                    <div class="alert alert-info mb-0">
+                                        <i class="bi bi-info-circle"></i>
+                                        <strong>智能重测功能:</strong>系统会自动检测延迟超过2000ms的节点,并在所有节点测速完成后重新测试这些高延迟节点,以防止误判。
+                                    </div>
+                                </div>
+                            </div>
                         </div>
                     </div>
                 </div>

+ 46 - 2
src/api/routes.js

@@ -227,6 +227,43 @@ router.post('/test/manual', async (req, res) => {
     const speedTester = new SpeedTester();
     const results = await speedTester.testNodes(nodes);
 
+    // 检查是否有高延迟节点需要重测
+    const highLatencyNodes = [];
+    const highLatencyResults = [];
+    
+    for (let i = 0; i < nodes.length; i++) {
+      const result = results[i];
+      if (result && result.isSuccess && result.latency && result.latency > 2000) {
+        highLatencyNodes.push(nodes[i]);
+        highLatencyResults.push(result);
+      }
+    }
+
+    // 如果有高延迟节点,进行重测
+    if (highLatencyNodes.length > 0) {
+      logger.info(`手动测试发现 ${highLatencyNodes.length} 个高延迟节点,开始重测`);
+      
+      // 重测高延迟节点
+      const retestResults = await speedTester.testNodes(highLatencyNodes);
+      
+      // 更新测试结果,使用重测的结果
+      for (let i = 0; i < highLatencyNodes.length; i++) {
+        const node = highLatencyNodes[i];
+        const retestResult = retestResults[i];
+        const originalIndex = results.findIndex(r => r.nodeId === node.id);
+        
+        if (originalIndex !== -1 && retestResult) {
+          // 如果重测结果更好,使用重测结果
+          if (retestResult.isSuccess && retestResult.latency && retestResult.latency <= 2000) {
+            results[originalIndex] = retestResult;
+            logger.info(`节点 ${node.name} 重测成功,延迟从 ${highLatencyResults[i].latency}ms 改善到 ${retestResult.latency}ms`);
+          } else {
+            logger.info(`节点 ${node.name} 重测后仍为高延迟: ${retestResult.latency || '超时'}ms`);
+          }
+        }
+      }
+    }
+
     // 处理测试结果并更新节点状态
     const scheduler = new (require('../core/scheduler'))();
     await scheduler.processTestResults(nodes, results);
@@ -234,8 +271,15 @@ router.post('/test/manual', async (req, res) => {
     // 发送测试总结报告
     await scheduler.sendTestSummary(nodes, results);
 
-    logger.info('手动测试完成', { testedNodes: nodes.length });
-    res.json({ success: true, data: { results, testedNodes: nodes.length } });
+    logger.info('手动测试完成', { testedNodes: nodes.length, retestedNodes: highLatencyNodes.length });
+    res.json({ 
+      success: true, 
+      data: { 
+        results, 
+        testedNodes: nodes.length,
+        retestedNodes: highLatencyNodes.length
+      } 
+    });
   } catch (error) {
     logger.error('手动测试失败', { error: error.message });
     res.status(500).json({ success: false, error: error.message });

+ 47 - 10
src/core/scheduler.js

@@ -11,7 +11,7 @@ class Scheduler {
     this.notifier = new TelegramNotifier();
     this.subscriptionManager = new SubscriptionManager();
     this.isRunning = false;
-    this.testInterval = parseInt(process.env.SPEED_TEST_INTERVAL) || 15; // 分钟
+    this.testInterval = parseInt(process.env.SPEED_TEST_INTERVAL) || 10; // 分钟
     this.failureThreshold = parseInt(process.env.NOTIFICATION_FAILURE_THRESHOLD) || 3;
     this.recoveryThreshold = parseInt(process.env.NOTIFICATION_RECOVERY_THRESHOLD) || 2;
   }
@@ -20,16 +20,16 @@ class Scheduler {
    * 启动调度器
    */
   start() {
-    logger.info('启动定时任务调度器 - 定时测速已关闭');
+    logger.info(`启动定时任务调度器 - 定时测速间隔: ${this.testInterval}分钟`);
 
-    // 暂时关闭定时测速
-    // const cronExpression = `*/${this.testInterval} * * * *`;
-    // this.speedTestJob = cron.schedule(cronExpression, async () => {
-    //   await this.runSpeedTest();
-    // }, {
-    //   scheduled: true,
-    //   timezone: 'Asia/Shanghai'
-    // });
+    // 启用定时测速
+    const cronExpression = `*/${this.testInterval} * * * *`;
+    this.speedTestJob = cron.schedule(cronExpression, async () => {
+      await this.runSpeedTest();
+    }, {
+      scheduled: true,
+      timezone: 'Asia/Shanghai'
+    });
 
     // 每小时重试失败的通知
     this.notificationRetryJob = cron.schedule('0 * * * *', async () => {
@@ -99,6 +99,43 @@ class Scheduler {
       // 批量测试节点
       const testResults = await this.speedTester.testNodes(nodes);
 
+      // 检查是否有高延迟节点需要重测
+      const highLatencyNodes = [];
+      const highLatencyResults = [];
+      
+      for (let i = 0; i < nodes.length; i++) {
+        const result = testResults[i];
+        if (result && result.isSuccess && result.latency && result.latency > 2000) {
+          highLatencyNodes.push(nodes[i]);
+          highLatencyResults.push(result);
+        }
+      }
+
+      // 如果有高延迟节点,进行重测
+      if (highLatencyNodes.length > 0) {
+        logger.info(`发现 ${highLatencyNodes.length} 个高延迟节点,开始重测`);
+        
+        // 重测高延迟节点
+        const retestResults = await this.speedTester.testNodes(highLatencyNodes);
+        
+        // 更新测试结果,使用重测的结果
+        for (let i = 0; i < highLatencyNodes.length; i++) {
+          const node = highLatencyNodes[i];
+          const retestResult = retestResults[i];
+          const originalIndex = testResults.findIndex(r => r.nodeId === node.id);
+          
+          if (originalIndex !== -1 && retestResult) {
+            // 如果重测结果更好,使用重测结果
+            if (retestResult.isSuccess && retestResult.latency && retestResult.latency <= 2000) {
+              testResults[originalIndex] = retestResult;
+              logger.info(`节点 ${node.name} 重测成功,延迟从 ${highLatencyResults[i].latency}ms 改善到 ${retestResult.latency}ms`);
+            } else {
+              logger.info(`节点 ${node.name} 重测后仍为高延迟: ${retestResult.latency || '超时'}ms`);
+            }
+          }
+        }
+      }
+
       // 处理测试结果
       await this.processTestResults(nodes, testResults);
 

+ 0 - 1
src/core/speedTester.js

@@ -1062,7 +1062,6 @@ class SpeedTester {
   async saveTestResult(testResult) {
     try {
       await TestResult.create(testResult);
-      logger.debug(`测试结果已保存: ${testResult.nodeId}`);
     } catch (error) {
       logger.error(`保存测试结果失败: ${error.message}`);
     }

+ 1 - 1
src/utils/logger.js

@@ -31,7 +31,7 @@ const consoleFormat = winston.format.combine(
 
 // 创建logger实例
 const logger = winston.createLogger({
-  level: process.env.NODE_ENV === 'production' ? 'info' : 'debug',
+  level: process.env.NODE_ENV === 'production' ? 'info' : 'info',
   format: logFormat,
   defaultMeta: { service: 'clash-speed-test' },
   transports: [