Files
xyzw_web_helper/MD说明文件夹/架构优化-100并发稳定运行方案v3.13.0.md
2025-10-17 20:56:50 +08:00

1046 lines
27 KiB
Markdown
Raw Permalink 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.

# 架构优化 - 100并发稳定运行方案 v3.13.0
**版本**: v3.13.0
**日期**: 2025-10-08
**目标**: 实现100个Token同时并发稳定运行
## 目标分析
**用户需求**
> "我是最终想要100同时并发稳定该如何进行优化WSS链接呢"
**核心挑战**
```
当前瓶颈:
1. 浏览器WebSocket连接数限制10-20个
2. 游戏服务器连接数限制约20-50个/IP
3. 网络带宽限制上行10-20Mbps
4. 系统资源限制内存、CPU
目标要求:
✅ 100个Token同时执行
✅ 稳定性 >95%
✅ 不降低执行效率
✅ 浏览器不卡顿
```
## 方案对比
| 方案 | 技术难度 | 稳定性 | 效率 | 推荐度 |
|------|---------|--------|------|--------|
| **方案A连接池+轮转** | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
| 方案B分组批次 | ⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐ |
| 方案C动态连接管理 | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ |
| 方案D混合HTTP/WSS | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
| 方案E代理服务器 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ |
---
## 🏆 方案A连接池 + 轮转策略(最推荐)
### 核心思想
```
不是100个连接同时存在而是
- 维持10-20个活跃WebSocket连接连接池
- 100个任务排队轮流使用这些连接
- 用完立即释放,给下一个任务使用
类比:
10个电话亭100个人排队打电话
每个人打完立即让给下一个人
```
### 架构设计
```
┌─────────────────────────────────────────────────┐
│ 100 个 Token 任务队列 │
│ [T1][T2][T3]...[T20][T21]...[T100] │
└─────────────────────────────────────────────────┘
↓ 排队获取连接
┌─────────────────────────────────────────────────┐
│ WebSocket 连接池20个连接
│ [WSS1][WSS2]...[WSS20] │
│ ↑使用中 ↑空闲 ↑使用中 │
└─────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────┐
│ 游戏服务器 │
└─────────────────────────────────────────────────┘
流程:
1. Token1 获取 WSS1执行任务
2. Token1 完成,释放 WSS1
3. Token21 立即获取 WSS1继续执行
4. 循环往复直到100个全部完成
```
### 代码实现
#### 1. WebSocket连接池类
```javascript
// src/utils/WebSocketPool.js
/**
* WebSocket连接池管理器
* 解决100并发问题的核心复用有限的WebSocket连接
*/
export class WebSocketPool {
constructor(options = {}) {
this.poolSize = options.poolSize || 20 // 连接池大小
this.connections = new Map() // 所有连接: tokenId -> connection
this.availableConnections = [] // 空闲连接队列
this.waitingQueue = [] // 等待获取连接的任务队列
this.activeCount = 0 // 当前活跃连接数
this.reconnectWebSocket = options.reconnectWebSocket // 连接函数
this.closeConnection = options.closeConnection // 关闭连接函数
// 统计信息
this.stats = {
totalAcquired: 0,
totalReleased: 0,
totalWaiting: 0,
maxWaitTime: 0,
avgWaitTime: 0
}
}
/**
* 获取一个可用的WebSocket连接
* @param {string} tokenId - Token ID
* @returns {Promise<Object>} WebSocket客户端
*/
async acquire(tokenId) {
const startTime = Date.now()
console.log(`🎫 [连接池] Token ${tokenId} 请求连接 (活跃: ${this.activeCount}/${this.poolSize}, 等待: ${this.waitingQueue.length})`)
return new Promise(async (resolve, reject) => {
// 尝试获取连接的函数
const tryAcquire = async () => {
// 方式1复用已有的连接
if (this.availableConnections.length > 0) {
const existingTokenId = this.availableConnections.shift()
const connection = this.connections.get(existingTokenId)
if (connection && connection.status === 'connected') {
// 更新连接的当前使用者
connection.currentUser = tokenId
connection.lastUsedTime = Date.now()
this.activeCount++
const waitTime = Date.now() - startTime
this.updateStats('acquired', waitTime)
console.log(`♻️ [连接池] Token ${tokenId} 复用连接 ${existingTokenId} (等待 ${waitTime}ms)`)
resolve(connection.client)
return true
} else {
// 连接已失效,移除
this.connections.delete(existingTokenId)
}
}
// 方式2创建新连接如果未达上限
if (this.connections.size < this.poolSize) {
try {
console.log(`🆕 [连接池] 为 Token ${tokenId} 创建新连接 (${this.connections.size + 1}/${this.poolSize})`)
const client = await this.reconnectWebSocket(tokenId)
if (!client) {
throw new Error('连接创建失败')
}
const connection = {
tokenId: tokenId,
client: client,
status: 'connected',
currentUser: tokenId,
createdTime: Date.now(),
lastUsedTime: Date.now()
}
this.connections.set(tokenId, connection)
this.activeCount++
const waitTime = Date.now() - startTime
this.updateStats('acquired', waitTime)
console.log(`✅ [连接池] Token ${tokenId} 创建连接成功 (等待 ${waitTime}ms)`)
resolve(client)
return true
} catch (error) {
console.error(`❌ [连接池] Token ${tokenId} 创建连接失败:`, error)
reject(error)
return false
}
}
return false
}
// 立即尝试获取
const acquired = await tryAcquire()
if (!acquired) {
// 需要等待,加入队列
console.log(`⏳ [连接池] Token ${tokenId} 加入等待队列 (队列长度: ${this.waitingQueue.length + 1})`)
this.waitingQueue.push({
tokenId,
resolve,
reject,
startTime,
tryAcquire
})
this.stats.totalWaiting++
}
})
}
/**
* 释放连接,供其他任务使用
* @param {string} tokenId - Token ID
*/
release(tokenId) {
const connection = this.connections.get(tokenId)
if (!connection) {
console.warn(`⚠️ [连接池] Token ${tokenId} 的连接不存在`)
return
}
console.log(`🔓 [连接池] Token ${tokenId} 释放连接 (活跃: ${this.activeCount - 1}/${this.poolSize}, 等待: ${this.waitingQueue.length})`)
this.activeCount--
connection.currentUser = null
this.updateStats('released')
// 如果有等待的任务,立即分配给它
if (this.waitingQueue.length > 0) {
const waiting = this.waitingQueue.shift()
console.log(`🔄 [连接池] 连接 ${tokenId} 分配给等待的 Token ${waiting.tokenId}`)
// 更新连接的使用者
connection.currentUser = waiting.tokenId
connection.lastUsedTime = Date.now()
this.activeCount++
const waitTime = Date.now() - waiting.startTime
this.updateStats('acquired', waitTime)
waiting.resolve(connection.client)
} else {
// 没有等待的任务,放入空闲队列
this.availableConnections.push(tokenId)
console.log(`💤 [连接池] 连接 ${tokenId} 进入空闲队列 (空闲: ${this.availableConnections.length})`)
}
}
/**
* 清理所有连接
*/
async cleanup() {
console.log(`🧹 [连接池] 开始清理,共 ${this.connections.size} 个连接`)
for (const [tokenId, connection] of this.connections.entries()) {
try {
await this.closeConnection(tokenId)
} catch (error) {
console.warn(`⚠️ [连接池] 关闭连接 ${tokenId} 失败:`, error)
}
}
this.connections.clear()
this.availableConnections = []
this.activeCount = 0
// 拒绝所有等待的任务
while (this.waitingQueue.length > 0) {
const waiting = this.waitingQueue.shift()
waiting.reject(new Error('连接池已清理'))
}
console.log(`✅ [连接池] 清理完成`)
}
/**
* 更新统计信息
*/
updateStats(type, waitTime = 0) {
if (type === 'acquired') {
this.stats.totalAcquired++
if (waitTime > this.stats.maxWaitTime) {
this.stats.maxWaitTime = waitTime
}
this.stats.avgWaitTime =
(this.stats.avgWaitTime * (this.stats.totalAcquired - 1) + waitTime) /
this.stats.totalAcquired
} else if (type === 'released') {
this.stats.totalReleased++
}
}
/**
* 获取连接池状态
*/
getStatus() {
return {
poolSize: this.poolSize,
totalConnections: this.connections.size,
activeConnections: this.activeCount,
availableConnections: this.availableConnections.length,
waitingTasks: this.waitingQueue.length,
stats: this.stats
}
}
/**
* 打印连接池状态
*/
printStatus() {
const status = this.getStatus()
console.log(`
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📊 [连接池状态]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
连接池大小: ${status.poolSize}
总连接数: ${status.totalConnections}
活跃连接: ${status.activeConnections}
空闲连接: ${status.availableConnections}
等待任务: ${status.waitingTasks}
统计信息:
- 总获取次数: ${status.stats.totalAcquired}
- 总释放次数: ${status.stats.totalReleased}
- 总等待次数: ${status.stats.totalWaiting}
- 最大等待时间: ${status.stats.maxWaitTime.toFixed(0)}ms
- 平均等待时间: ${status.stats.avgWaitTime.toFixed(0)}ms
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
`)
}
}
```
#### 2. 集成到 batchTaskStore.js
```javascript
// src/stores/batchTaskStore.js
import { WebSocketPool } from '@/utils/WebSocketPool'
// 在 store 中添加连接池实例
let wsPool = null
/**
* 初始化连接池
*/
const initWebSocketPool = (poolSize = 20) => {
if (wsPool) {
// 清理旧的连接池
wsPool.cleanup()
}
wsPool = new WebSocketPool({
poolSize,
reconnectWebSocket: tokenStore.reconnectWebSocket,
closeConnection: tokenStore.closeWebSocketConnection
})
console.log(`✅ [连接池] 初始化完成,大小: ${poolSize}`)
return wsPool
}
/**
* 使用连接池执行Token任务优化版
*/
const executeTokenTasksWithPool = async (tokenId, tasks) => {
const startTime = Date.now()
let client = null
try {
// 1. 从连接池获取连接
updateTaskProgress(tokenId, {
status: 'waiting',
message: '等待获取连接...'
})
client = await wsPool.acquire(tokenId)
updateTaskProgress(tokenId, {
status: 'executing',
startTime,
currentTask: `已获取连接,开始执行任务`
})
// 2. 执行任务(使用获取的连接)
const results = {}
let hasError = false
for (const task of tasks) {
if (isPaused.value) {
await new Promise(resolve => setTimeout(resolve, 500))
}
updateTaskProgress(tokenId, {
currentTask: `执行: ${task}`
})
try {
const result = await executeTask(tokenId, task, client)
results[task] = result
} catch (error) {
console.error(`❌ [${tokenId}] 任务 ${task} 失败:`, error)
results[task] = {
success: false,
error: error.message,
task
}
hasError = true
}
}
// 3. 更新最终状态
const endTime = Date.now()
const duration = ((endTime - startTime) / 1000).toFixed(1)
updateTaskProgress(tokenId, {
status: hasError ? 'failed' : 'completed',
endTime,
duration: `${duration}s`,
result: results,
error: hasError ? '部分任务失败' : null
})
// 4. 更新统计
if (hasError) {
executionStats.value.failed++
} else {
executionStats.value.success++
}
} catch (error) {
// 连接获取或执行失败
const endTime = Date.now()
const duration = ((endTime - startTime) / 1000).toFixed(1)
console.error(`❌ [${tokenId}] 执行失败:`, error)
updateTaskProgress(tokenId, {
status: 'failed',
endTime,
duration: `${duration}s`,
error: error.message || String(error)
})
executionStats.value.failed++
} finally {
// 5. 释放连接(关键!)
if (client) {
wsPool.release(tokenId)
}
}
}
/**
* 使用连接池执行批量任务
*/
const executeBatchWithPool = async (tokenIds, tasks) => {
console.log(`
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🚀 [连接池模式] 开始批量执行
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Token数量: ${tokenIds.length}
连接池大小: ${wsPool.poolSize}
任务列表: ${tasks.join(', ')}
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
`)
// 所有任务并发启动(但会在连接池内排队)
const promises = tokenIds.map(tokenId =>
executeTokenTasksWithPool(tokenId, tasks)
)
// 每隔5秒打印一次连接池状态
const statusInterval = setInterval(() => {
wsPool.printStatus()
}, 5000)
// 等待所有任务完成
await Promise.all(promises)
// 清理定时器
clearInterval(statusInterval)
// 打印最终状态
wsPool.printStatus()
}
/**
* 修改 startBatchExecution 使用连接池
*/
const startBatchExecution = async (
tokens = null,
tasks = null,
isRetry = false,
continueFromSaved = false
) => {
try {
// ... 前面的代码保持不变 ...
// 🆕 初始化连接池从localStorage读取配置
const poolSize = parseInt(localStorage.getItem('wsPoolSize') || '20')
initWebSocketPool(poolSize)
// 🆕 使用连接池模式执行
await executeBatchWithPool(tokensToExecute, targetTasks)
// 完成执行
finishBatchExecution()
} catch (error) {
console.error('批量执行失败:', error)
// ...
} finally {
// 🆕 清理连接池
if (wsPool) {
await wsPool.cleanup()
wsPool = null
}
}
}
```
### 优势分析
**突破浏览器限制**
```
传统方式: 100个连接 → 浏览器崩溃
连接池方式: 20个连接 → 100个任务轮转使用 → 稳定运行
```
**高效复用**
```
连接建立时间: 1-2秒
任务执行时间: 10-30秒
传统方式:
- 每个任务重新建立连接: 1-2秒浪费
- 100个任务: 浪费 100-200秒
连接池方式:
- 连接复用,无需重新建立
- 100个任务: 节省 100-200秒
```
**内存优化**
```
传统方式: 100连接 × 10MB = 1000MB
连接池方式: 20连接 × 10MB = 200MB
节省内存: 80%
```
**统计透明**
```
实时监控:
- 活跃连接数
- 等待任务数
- 平均等待时间
- 最大等待时间
```
---
## 🥈 方案B智能分组批次执行
### 核心思想
```
将100个Token分成多个批次
- 每批10个共10批
- 批内并发执行
- 批间无缝衔接前一批完成80%时启动下一批)
```
### 代码实现
```javascript
/**
* 智能分组批次执行
* 批次间无缝衔接,提高效率
*/
const executeBatchWithSmartGroups = async (tokenIds, tasks) => {
const BATCH_SIZE = 10 // 每批大小
const OVERLAP_THRESHOLD = 0.8 // 80%完成时启动下一批
const batches = []
for (let i = 0; i < tokenIds.length; i += BATCH_SIZE) {
batches.push(tokenIds.slice(i, i + BATCH_SIZE))
}
console.log(`📦 将${tokenIds.length}个Token分为${batches.length}批,每批${BATCH_SIZE}个`)
let currentBatchIndex = 0
let nextBatchStarted = false
const executeBatch = async (batch, batchIndex) => {
console.log(`
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🔥 执行第 ${batchIndex + 1}/${batches.length}
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Token数量: ${batch.length}
Token列表: ${batch.join(', ')}
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
`)
const promises = batch.map((tokenId, index) =>
executeTokenTasks(tokenId, tasks).then(() => {
// 检查是否该启动下一批
const completed = index + 1
const progress = completed / batch.length
if (
progress >= OVERLAP_THRESHOLD &&
batchIndex < batches.length - 1 &&
!nextBatchStarted
) {
nextBatchStarted = true
console.log(`⚡ 第${batchIndex + 1}批已完成${(progress * 100).toFixed(0)}%,启动下一批`)
executeBatch(batches[batchIndex + 1], batchIndex + 1)
}
})
)
await Promise.all(promises)
console.log(`✅ 第 ${batchIndex + 1}/${batches.length} 批执行完成`)
}
// 启动第一批
await executeBatch(batches[0], 0)
}
```
### 时间效率对比
```
顺序执行(保守):
批次1: 0-60秒 (10个Token)
批次2: 60-120秒
批次3: 120-180秒
...
总时间: 600秒
无缝衔接(优化):
批次1: 0-60秒 (10个Token)
批次2: 48-108秒 (80%时启动)
批次3: 96-156秒
...
总时间: 约420秒
节省时间: 30%
```
---
## 🥉 方案C动态连接管理
### 核心思想
```
根据任务阶段动态管理连接:
1. 准备阶段:不建立连接
2. 执行阶段:建立连接
3. 完成阶段:立即断开连接
目标将同时活跃连接数控制在20以内
```
### 代码实现
```javascript
/**
* 动态连接管理器
*/
class DynamicConnectionManager {
constructor(maxConnections = 20) {
this.maxConnections = maxConnections
this.activeConnections = new Set()
this.pendingTasks = []
}
async executeWithConnection(tokenId, taskFn) {
// 等待直到可以建立连接
while (this.activeConnections.size >= this.maxConnections) {
await new Promise(resolve => setTimeout(resolve, 100))
}
// 建立连接
this.activeConnections.add(tokenId)
console.log(`🔗 建立连接: ${tokenId} (活跃: ${this.activeConnections.size}/${this.maxConnections})`)
try {
// 执行任务
const result = await taskFn()
return result
} finally {
// 立即断开连接
this.activeConnections.delete(tokenId)
console.log(`🔌 断开连接: ${tokenId} (活跃: ${this.activeConnections.size}/${this.maxConnections})`)
// 关闭WebSocket
await tokenStore.closeWebSocketConnection(tokenId)
}
}
}
const connManager = new DynamicConnectionManager(20)
const executeTokenTasksDynamic = async (tokenId, tasks) => {
return connManager.executeWithConnection(tokenId, async () => {
// 建立连接
const client = await tokenStore.reconnectWebSocket(tokenId)
// 执行所有任务
const results = {}
for (const task of tasks) {
results[task] = await executeTask(tokenId, task, client)
}
return results
})
}
```
---
## ⭐ 方案D混合HTTP/WSS模式终极方案
### 核心思想
```
分析任务特性,分类处理:
- 实时任务需要推送使用WebSocket
- 非实时任务(请求-响应使用HTTP API
例如:
WebSocket任务: 爬塔、发车(需要实时状态)
HTTP任务: 签到、领奖、答题(一次性操作)
```
### 任务分类
```javascript
const TASK_CATEGORIES = {
// WebSocket任务需要保持连接
realtime: [
'climbTower', // 爬塔
'sendCar', // 发车
'pvpBattle', // PVP对战
],
// HTTP任务可以用API
oneTime: [
'dailySignIn', // 每日签到
'legionSignIn', // 俱乐部签到
'claimReward', // 领取奖励
'autoStudy', // 一键答题
'consumeResources', // 消耗资源
'addClock', // 加钟
'claimHangupReward', // 领取挂机奖励
]
}
```
### HTTP API 实现
```javascript
/**
* HTTP API调用替代部分WebSocket
*/
const executeHttpTask = async (tokenId, task) => {
const token = tokenStore.gameTokens.find(t => t.id === tokenId)
if (!token) throw new Error('Token不存在')
const apiUrl = 'https://xxz-xyzw.hortorgames.com/api'
// 根据任务类型构建请求
const requestConfig = buildHttpRequest(task, token)
try {
const response = await fetch(`${apiUrl}/${requestConfig.endpoint}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${token.roleToken}`,
...requestConfig.headers
},
body: JSON.stringify(requestConfig.body)
})
const result = await response.json()
return result
} catch (error) {
console.error(`HTTP任务失败: ${task}`, error)
throw error
}
}
/**
* 混合执行模式
*/
const executeTokenTasksHybrid = async (tokenId, tasks) => {
const httpTasks = tasks.filter(t => TASK_CATEGORIES.oneTime.includes(t))
const wsTasks = tasks.filter(t => TASK_CATEGORIES.realtime.includes(t))
const results = {}
// 1. 先执行HTTP任务不占用WebSocket连接
for (const task of httpTasks) {
try {
results[task] = await executeHttpTask(tokenId, task)
console.log(`✅ HTTP任务完成: ${task}`)
} catch (error) {
results[task] = { success: false, error: error.message }
}
}
// 2. 再执行WebSocket任务从连接池获取
if (wsTasks.length > 0) {
const client = await wsPool.acquire(tokenId)
try {
for (const task of wsTasks) {
results[task] = await executeTask(tokenId, task, client)
console.log(`✅ WSS任务完成: ${task}`)
}
} finally {
wsPool.release(tokenId)
}
}
return results
}
```
### 优势
```
假设每个Token有10个任务
- 7个HTTP任务
- 3个WebSocket任务
传统方式:
- 需要WebSocket连接: 100%时间
- 连接池压力: 大
- 等待时间: 长
混合方式:
- 需要WebSocket连接: 30%时间
- 连接池压力: 小
- 等待时间: 短
- 效率提升: 约2-3倍
```
---
## 方案E本地代理服务器高级方案
### 核心思想
```
架构:
浏览器 ←→ 本地Node.js代理 ←→ 游戏服务器
(1个) (管理100个连接) (接受100个连接)
流程:
1. 浏览器通过HTTP/WebSocket连接本地代理
2. 代理服务器维护到游戏服务器的100个连接
3. 浏览器发送指令,代理转发到对应连接
```
### 简化实现
```javascript
// local-proxy-server.js
const WebSocket = require('ws')
const express = require('express')
const app = express()
const server = require('http').createServer(app)
const wss = new WebSocket.Server({ server })
// 存储到游戏服务器的连接
const gameConnections = new Map()
// 浏览器连接到代理
wss.on('connection', (clientWs) => {
console.log('浏览器已连接')
clientWs.on('message', async (message) => {
const data = JSON.parse(message)
const { tokenId, action, payload } = data
// 获取或创建到游戏服务器的连接
let gameWs = gameConnections.get(tokenId)
if (!gameWs || gameWs.readyState !== WebSocket.OPEN) {
gameWs = new WebSocket(gameServerUrl)
gameConnections.set(tokenId, gameWs)
}
// 转发到游戏服务器
gameWs.send(JSON.stringify(payload))
// 监听游戏服务器响应
gameWs.on('message', (response) => {
// 转发回浏览器
clientWs.send(JSON.stringify({
tokenId,
response: JSON.parse(response)
}))
})
})
})
server.listen(8080, () => {
console.log('代理服务器运行在 http://localhost:8080')
})
```
### 优缺点
**优点**
- ✅ 完全突破浏览器限制
- ✅ 可以管理任意数量的连接
- ✅ 更好的错误处理和重连
**缺点**
- ❌ 需要安装Node.js
- ❌ 需要运行额外的服务器
- ❌ 部署复杂度高
---
## 推荐实施路线
### 阶段1快速验证1-2天
**实施方案B智能分组批次**
优势:
- 代码改动最小
- 立即可用
- 稳定性好
配置:
```javascript
BATCH_SIZE = 10
OVERLAP_THRESHOLD = 0.8
总批次 = 10
预计时间 = 约7-8分钟100个Token
```
### 阶段2性能优化3-5天
**实施方案A连接池 + 轮转**
优势:
- 真正的100并发
- 资源利用率高
- 可扩展性强
配置:
```javascript
POOL_SIZE = 20
真实并发 = 100个任务
活跃连接 = 20
预计时间 = 约5-6分钟100个Token
```
### 阶段3终极优化1-2周
**实施方案D混合HTTP/WSS**
优势:
- 最高效率
- 最低资源占用
- 最稳定
配置:
```javascript
HTTP任务比例 = 70%
WSS任务比例 = 30%
连接池大小 = 10-15
预计时间 = 约3-4分钟100个Token
```
---
## 性能对比总结
| 方案 | 100Token耗时 | 内存占用 | 实施难度 | 稳定性 |
|------|-------------|---------|---------|--------|
| 当前方案(20并发) | ~15分钟 | 200MB | - | ⭐⭐⭐⭐ |
| 方案B(分组批次) | ~8分钟 | 200MB | ⭐⭐ | ⭐⭐⭐⭐⭐ |
| 方案A(连接池) | ~6分钟 | 200MB | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
| 方案D(混合模式) | ~4分钟 | 150MB | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
| 方案E(代理服务器) | ~3分钟 | 500MB | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
---
## 立即行动建议
### 建议1先实施方案A连接池
**理由**
- ✅ 投入产出比最高
- ✅ 实施难度中等
- ✅ 效果显著15分钟 → 6分钟
- ✅ 稳定性excellent
### 建议2测试配置
```javascript
// 第一次测试
{
mode: '连接池',
poolSize: 15,
tokenCount: 50, // 先测50个
tasks: ['完整套餐']
}
// 如果成功,扩大规模
{
poolSize: 20,
tokenCount: 100,
tasks: ['完整套餐']
}
```
### 建议3监控指标
```
关注以下指标:
1. 连接成功率 (目标 >98%)
2. 任务成功率 (目标 >95%)
3. 平均等待时间 (目标 <5秒)
4. 总执行时间 (目标 <10分钟)
5. 浏览器内存 (目标 <500MB)
```
---
**状态**: ✅ 方案已提供
**推荐实施**: 方案A连接池 + 方案D混合模式
**预期效果**: 100并发稳定运行总耗时 4-6分钟