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

27 KiB
Raw Permalink Blame History

架构优化 - 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连接池类

// 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

// 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%时启动下一批)

代码实现

/**
 * 智能分组批次执行
 * 批次间无缝衔接,提高效率
 */
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以内

代码实现

/**
 * 动态连接管理器
 */
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任务: 签到、领奖、答题(一次性操作)

任务分类

const TASK_CATEGORIES = {
  // WebSocket任务需要保持连接
  realtime: [
    'climbTower',      // 爬塔
    'sendCar',         // 发车
    'pvpBattle',       // PVP对战
  ],
  
  // HTTP任务可以用API
  oneTime: [
    'dailySignIn',     // 每日签到
    'legionSignIn',    // 俱乐部签到
    'claimReward',     // 领取奖励
    'autoStudy',       // 一键答题
    'consumeResources', // 消耗资源
    'addClock',        // 加钟
    'claimHangupReward', // 领取挂机奖励
  ]
}

HTTP API 实现

/**
 * 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. 浏览器发送指令,代理转发到对应连接

简化实现

// 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智能分组批次

优势:

  • 代码改动最小
  • 立即可用
  • 稳定性好

配置:

BATCH_SIZE = 10
OVERLAP_THRESHOLD = 0.8
总批次 = 10
预计时间 = 约7-8分钟100个Token

阶段2性能优化3-5天

实施方案A连接池 + 轮转

优势:

  • 真正的100并发
  • 资源利用率高
  • 可扩展性强

配置:

POOL_SIZE = 20
真实并发 = 100个任务
活跃连接 = 20
预计时间 = 约5-6分钟100个Token

阶段3终极优化1-2周

实施方案D混合HTTP/WSS

优势:

  • 最高效率
  • 最低资源占用
  • 最稳定

配置:

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测试配置

// 第一次测试
{
  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分钟