# 架构优化 - 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分钟

