# 性能分析 - 并发数超过20导致WSS连接失败 v3.12.8 **版本**: v3.12.8 **日期**: 2025-10-08 **类型**: 性能分析 / 使用建议 ## 问题描述 用户反馈: > "我发现并发的数量超过20个,就很容易导致WSS链接失败,这是什么原因导致的" **现象**: - 并发数设置为20以下:稳定运行 ✅ - 并发数设置为20-30:偶尔连接失败 ⚠️ - 并发数设置为30+:频繁连接失败 ❌ ## 根本原因分析 ### 1. 浏览器WebSocket连接数限制 ⭐ 主要原因 **浏览器限制**: - **Chrome/Edge**: 每个域名最多约 **255-256** 个WebSocket连接(理论值) - **实际安全值**: 每个域名建议 **10-20** 个并发连接 - **Firefox**: 约 **200** 个连接 - **Safari**: 约 **100** 个连接 **为什么实际值远小于理论值?** ``` 理论最大值: 256个 实际推荐值: 10-20个 原因: 1. 浏览器资源限制(内存、CPU) 2. 网络带宽限制 3. 操作系统的Socket限制 4. 浏览器的性能保护机制 ``` ### 2. 游戏服务器连接限制 **服务器端可能的限制**: ``` 1. 同一IP连接数限制 - 防止DDoS攻击 - 限制单个用户的连接数 - 通常限制:10-50个/IP 2. 连接速率限制 - 限制连接建立速度 - 防止批量自动化 - 例如:1秒内最多建立5个连接 3. 资源保护 - 服务器总连接数限制 - 单个用户资源配额 - 防止服务器过载 ``` ### 3. 连接建立速度过快 **当前的连接间隔**: ```javascript const delayMs = connectionIndex * 500 // 每个连接间隔500ms ``` **并发20个时的时间分布**: ``` 连接1: 0秒 ← 立即开始 连接2: 0.5秒 连接3: 1.0秒 连接4: 1.5秒 ... 连接10: 4.5秒 ... 连接20: 9.5秒 ← 最后一个连接在9.5秒后开始 ``` **问题**: - 虽然有间隔,但10秒内建立20个连接 - 可能触发服务器的反批量检测 - 服务器可能认为这是自动化攻击 ### 4. 内存和资源占用 **单个WebSocket连接的资源消耗**: ``` 内存占用: 约 5-10MB / 连接 网络带宽: 约 100KB-1MB / 连接(活跃时) CPU占用: 约 1-2% / 连接(活跃时) 20个并发连接: 内存: 100-200MB 带宽: 2-20MB CPU: 20-40% ``` **浏览器性能影响**: ``` 并发10个: 流畅 ✅ 并发20个: 可接受 ⚠️ 并发50个: 卡顿明显 ❌ 并发100个: 浏览器可能崩溃 💥 ``` ### 5. 网络质量影响 **网络因素**: ``` 1. 家庭宽带上行带宽限制 - 下载速度: 100Mbps - 上传速度: 10-20Mbps ← 瓶颈 - 20个连接可能超过上行带宽 2. 路由器NAT表限制 - 家用路由器通常支持 1000-5000 个并发连接 - 但实际稳定值更低 - 过多连接可能导致路由器不稳定 3. ISP限制 - 运营商可能限制同时连接数 - 防止P2P等高并发应用 ``` ## 技术限制详解 ### 浏览器WebSocket实现 ```javascript // Chrome的WebSocket实现(简化) class WebSocket { constructor(url) { // 1. 检查连接数 if (activeConnections >= MAX_CONNECTIONS_PER_DOMAIN) { throw new Error('Too many connections') } // 2. 建立TCP连接 // 3. WebSocket握手 // 4. 维护心跳 } } // 限制机制 const MAX_CONNECTIONS_PER_DOMAIN = 256 // 理论值 const RECOMMENDED_LIMIT = 10-20 // 实际安全值 ``` ### 操作系统限制 **Windows**: ``` 默认最大Socket数: 65535(理论) 实际推荐值: 5000-10000 单个进程限制: 2000-5000 ``` **macOS/Linux**: ``` 默认限制: 1024(ulimit -n) 可调整为: 65535 但实际使用建议: 5000以下 ``` ## 当前实现分析 ### 连接建立流程 ```javascript // src/stores/batchTaskStore.js const executeBatchWithConcurrency = async (tokenIds, tasks) => { const queue = [...tokenIds] const executing = [] let connectionIndex = 0 while (queue.length > 0 || executing.length > 0) { // 填充执行队列(最多maxConcurrency个) while (executing.length < maxConcurrency.value && queue.length > 0) { const tokenId = queue.shift() // 错开连接时间 const delayMs = connectionIndex * 500 // 500ms间隔 connectionIndex++ const promise = (async () => { if (delayMs > 0) { await new Promise(resolve => setTimeout(resolve, delayMs)) } // 建立连接并执行任务 return executeTokenTasks(tokenId, tasks) })() executing.push(promise) } // 等待至少一个完成 if (executing.length > 0) { await Promise.race(executing) } } } ``` ### 问题分析 1. **累加的延迟时间**: ``` 第1个: 0ms 第2个: 500ms 第3个: 1000ms ... 第20个: 9500ms 问题:前面的连接可能已经完成, 但新连接仍在累加延迟 ``` 2. **并发控制不精确**: ``` 虽然限制了executing.length < maxConcurrency 但实际活跃的WebSocket连接数可能更多 因为连接建立和任务执行是异步的 ``` 3. **没有连接失败重试限制**: ``` 连接失败会重试,但可能加剧连接压力 ``` ## 解决方案和建议 ### 方案1:降低推荐并发数 ⭐ 推荐 **建议的安全值**: | 网络环境 | 推荐并发数 | 说明 | |---------|----------|------| | **家庭宽带** | **10-15** | 最稳定,适合大多数用户 | | 高速宽带 | 15-20 | 网络条件好可以尝试 | | 企业网络 | 20-30 | 专线网络,上行带宽足够 | | 服务器环境 | 30-50 | 数据中心,网络质量极好 | **实施**: ```javascript // src/stores/batchTaskStore.js const maxConcurrency = ref( parseInt(localStorage.getItem('maxConcurrency') || '10') // 默认改为10 ) // 添加警告提示 const setMaxConcurrency = (count) => { if (count > 20) { console.warn(`⚠️ 警告:并发数 ${count} 超过推荐值(20)`) console.warn(`⚠️ 可能导致WebSocket连接失败、浏览器卡顿等问题`) console.warn(`⚠️ 建议设置为10-20之间`) } maxConcurrency.value = count localStorage.setItem('maxConcurrency', count.toString()) } ``` ### 方案2:优化连接间隔策略 **当前策略问题**: ```javascript const delayMs = connectionIndex * 500 // 累加延迟 // 第20个要等9.5秒,但前面的可能已经完成了 ``` **优化策略**: ```javascript // 固定间隔,不累加 const CONNECTION_INTERVAL = 1000 // 每个连接间隔1秒 let lastConnectionTime = 0 while (executing.length < maxConcurrency.value && queue.length > 0) { const tokenId = queue.shift() // 计算需要等待的时间 const now = Date.now() const timeSinceLastConnection = now - lastConnectionTime const waitTime = Math.max(0, CONNECTION_INTERVAL - timeSinceLastConnection) if (waitTime > 0) { await new Promise(resolve => setTimeout(resolve, waitTime)) } lastConnectionTime = Date.now() // 建立连接... } ``` ### 方案3:添加连接池管理 ```javascript // 连接池配置 const CONNECTION_POOL_CONFIG = { maxConnections: 20, // 最大连接数 maxActiveConnections: 10, // 最大活跃连接数 connectionTimeout: 30000, // 连接超时30秒 idleTimeout: 60000, // 空闲超时60秒 connectionInterval: 1000 // 连接间隔1秒 } // 连接池管理 class WebSocketPool { constructor(config) { this.config = config this.activeConnections = new Map() this.pendingQueue = [] } async acquire(tokenId) { // 等待直到可以建立新连接 while (this.activeConnections.size >= this.config.maxActiveConnections) { await new Promise(resolve => setTimeout(resolve, 100)) } // 建立连接 const connection = await this.createConnection(tokenId) this.activeConnections.set(tokenId, connection) return connection } release(tokenId) { this.activeConnections.delete(tokenId) } } ``` ### 方案4:分批执行 ```javascript // 将Token分批执行,每批不超过10个 const BATCH_SIZE = 10 const BATCH_INTERVAL = 5000 // 批次间隔5秒 for (let i = 0; i < tokenIds.length; i += BATCH_SIZE) { const batch = tokenIds.slice(i, i + BATCH_SIZE) console.log(`━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━`) console.log(`🔄 执行第 ${Math.floor(i / BATCH_SIZE) + 1} 批`) console.log(`📊 本批数量: ${batch.length}`) console.log(`━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━`) // 执行这一批 await executeBatch(batch, tasks) // 批次间隔 if (i + BATCH_SIZE < tokenIds.length) { console.log(`⏸️ 等待${BATCH_INTERVAL/1000}秒后执行下一批...`) await new Promise(resolve => setTimeout(resolve, BATCH_INTERVAL)) } } ``` ## 用户使用建议 ### 1. 根据Token数量选择并发数 ``` Token总数 推荐并发数 预计时间 -------------------------------------- 1-10个 5-7 2-3分钟 10-50个 7-10 5-8分钟 50-100个 10-15 8-12分钟 100-500个 10-15 20-60分钟 500-1000个 10-15 60-120分钟 ``` ### 2. 网络环境优化 **家庭网络**: ``` 1. 使用有线连接(比WiFi更稳定) 2. 关闭其他占用带宽的应用 3. 避免高峰时段(晚上8-10点) 4. 重启路由器清理NAT表 5. 并发数设置为10-12 ``` **移动热点**: ``` 1. 4G/5G热点通常上行带宽较低 2. 建议并发数: 5-8 3. 避免流量不足时执行 4. 注意流量消耗 ``` **企业/学校网络**: ``` 1. 可能有防火墙限制 2. 可能禁止WebSocket 3. 建议先小规模测试 4. 并发数: 10-15 ``` ### 3. 分时段执行 ```javascript // 方案A:深夜执行(服务器压力小) 定时时间: 凌晨2:00-5:00 并发数: 可以设置高一些 (15-20) 稳定性: ⭐⭐⭐⭐⭐ // 方案B:白天执行 定时时间: 上午10:00-下午4:00 并发数: 中等 (10-12) 稳定性: ⭐⭐⭐⭐ // 方案C:高峰时段(不推荐) 定时时间: 晚上8:00-10:00 并发数: 低 (5-8) 稳定性: ⭐⭐ ``` ### 4. 监控和调整 **观察指标**: ``` 1. WebSocket连接成功率 - >95%: 并发数合适 ✅ - 90-95%: 可以接受 ⚠️ - <90%: 降低并发数 ❌ 2. 任务执行失败率 - <5%: 正常 ✅ - 5-10%: 注意观察 ⚠️ - >10%: 需要优化 ❌ 3. 浏览器响应速度 - 流畅: 合适 ✅ - 偶尔卡顿: 可接受 ⚠️ - 频繁卡顿: 降低并发 ❌ ``` **调整策略**: ``` 步骤1: 从10开始测试 步骤2: 观察连接成功率和失败率 步骤3: 如果稳定,可以逐步增加到12、15 步骤4: 如果出现问题,立即降低 步骤5: 找到最佳值后固定使用 ``` ## 错误排查 ### 常见错误和解决方法 #### 错误1:连接超时 ``` 错误信息: WebSocket connection timeout 原因: 服务器响应慢或网络不稳定 解决: 1. 降低并发数到10 2. 增加连接间隔到1000ms 3. 检查网络连接 ``` #### 错误2:连接被拒绝 ``` 错误信息: WebSocket connection refused 原因: 服务器限制连接数或IP被封 解决: 1. 立即停止批量任务 2. 等待5-10分钟 3. 降低并发数到5-8 4. 增加连接间隔到2000ms ``` #### 错误3:浏览器卡死 ``` 现象: 浏览器无响应,CPU 100% 原因: 并发数过高,资源耗尽 解决: 1. 强制刷新页面 (Ctrl+F5) 2. 清除浏览器缓存 3. 下次使用时降低并发数到5-10 ``` #### 错误4:部分Token连接失败 ``` 现象: 100个Token中20-30个连接失败 原因: 超过服务器或浏览器限制 解决: 1. 降低并发数 2. 使用"重试失败"功能 3. 分批执行 ``` ## 最佳实践总结 ### 稳定运行配置 ```javascript // 推荐配置 { maxConcurrency: 10, // 并发数 connectionInterval: 1000, // 连接间隔1秒 requestTimeout: 5000, // 请求超时5秒 maxRetries: 3, // 最大重试3次 retryDelay: 3000 // 重试延迟3秒 } ``` ### 性能vs稳定性权衡 ``` 高性能模式(不推荐): - 并发数: 30-50 - 连接间隔: 500ms - 风险: 高 - 稳定性: ⭐⭐ - 速度: ⭐⭐⭐⭐⭐ 平衡模式(推荐): - 并发数: 10-15 - 连接间隔: 1000ms - 风险: 低 - 稳定性: ⭐⭐⭐⭐ - 速度: ⭐⭐⭐⭐ 稳定模式: - 并发数: 5-8 - 连接间隔: 2000ms - 风险: 极低 - 稳定性: ⭐⭐⭐⭐⭐ - 速度: ⭐⭐⭐ ``` ## 技术限制对照表 | 限制类型 | 限制值 | 影响 | 建议 | |---------|--------|------|------| | 浏览器连接数 | 10-20/域名 | 超过会连接失败 | 并发≤15 | | 服务器限制 | 10-50/IP | 超过可能被封 | 并发≤20 | | 上行带宽 | 10-20Mbps | 影响连接速度 | 并发≤15 | | 浏览器内存 | 100-200MB | 影响性能 | 并发≤20 | | 路由器NAT | 1000-5000 | 连接不稳定 | 并发≤15 | ## 总结 **问题根源**: - 🔍 浏览器WebSocket连接数限制(10-20个) - 🔍 游戏服务器连接数限制 - 🔍 网络带宽限制(特别是上行) - 🔍 系统资源限制(内存、CPU) **推荐配置**: - ✅ **并发数**: 10-15(最佳平衡点) - ✅ **连接间隔**: 1000ms - ✅ **网络环境**: 有线连接优先 - ✅ **执行时段**: 避开高峰期 **关键建议**: - 💡 **不要盲目追求高并发**,稳定性更重要 - 💡 **从10开始测试**,逐步找到最佳值 - 💡 **关注连接成功率**,<95%就降低并发 - 💡 **使用进度保存**,连接失败可以继续 - 💡 **分时段执行**,深夜/凌晨最稳定 --- **状态**: ✅ 已分析 **版本**: v3.12.8 **推荐并发数**: 10-15