Skip to content

压力测试

📋 概述

压力测试是在极限条件下验证系统稳定性和可靠性的测试方法。通过超出正常工作负载的方式测试Node.js应用,压力测试帮助发现系统的破坏点、资源瓶颈和故障恢复能力,确保应用在异常情况下的稳定性和用户体验。

🎯 学习目标

  • 理解压力测试的核心概念和实施策略
  • 掌握压力测试工具的使用和配置
  • 学会设计有效的压力测试场景
  • 了解压力测试结果分析和系统优化方法

⚡ 压力测试基础概念

压力测试类型

mermaid
graph TB
    A[压力测试类型] --> B[负载压力测试<br/>Load Stress Testing]
    A --> C[容量压力测试<br/>Volume Stress Testing]
    A --> D[并发压力测试<br/>Concurrency Stress Testing]
    A --> E[内存压力测试<br/>Memory Stress Testing]
    A --> F[网络压力测试<br/>Network Stress Testing]
    
    B --> B1[逐步增加负载<br/>找出系统极限<br/>验证降级策略]
    C --> C1[大数据量处理<br/>存储容量测试<br/>数据库性能极限]
    D --> D1[高并发连接<br/>线程池压力<br/>锁竞争测试]
    E --> E1[内存泄漏检测<br/>垃圾回收压力<br/>OOM场景测试]
    F --> F1[网络带宽限制<br/>连接数极限<br/>超时处理验证]
    
    style B fill:#ffebee
    style C fill:#f3e5f5
    style D fill:#e8f5e8
    style E fill:#fff3e0
    style F fill:#e1f5fe

压力测试指标

javascript
const StressTestingMetrics = {
  BREAKING_POINT: {
    definition: '系统开始出现错误或性能急剧下降的临界点',
    measurements: [
      'Maximum Requests Per Second (最大RPS)',
      'Maximum Concurrent Users (最大并发用户)',
      'Resource Exhaustion Point (资源耗尽点)',
      'Response Time Breakdown (响应时间崩溃点)'
    ],
    indicators: [
      '错误率超过5%',
      'P95响应时间超过10秒',
      '内存使用率超过90%',
      'CPU使用率持续100%'
    ]
  },
  
  RECOVERY_METRICS: {
    definition: '系统从压力状态恢复正常的能力指标',
    measurements: [
      'Recovery Time (恢复时间)',
      'Data Integrity (数据完整性)',
      'Service Availability (服务可用性)',
      'Resource Cleanup (资源清理效率)'
    ],
    targets: [
      '恢复时间 < 5分钟',
      '数据零丢失',
      '服务自动恢复',
      '资源完全释放'
    ]
  },
  
  DEGRADATION_PATTERNS: {
    graceful: {
      description: '优雅降级',
      characteristics: [
        '错误率缓慢上升',
        '响应时间逐渐增加',
        '功能有序关闭',
        '用户体验平滑下降'
      ]
    },
    
    sudden: {
      description: '突然失效',
      characteristics: [
        '错误率急剧上升',
        '响应时间急剧增加',
        '服务突然不可用',
        '系统崩溃或超时'
      ]
    }
  }
};

🛠 压力测试工具和实现

Artillery.js 高强度压力测试

javascript
// artillery-stress-config.yml
config:
  target: 'http://localhost:3000'
  phases:
    # 阶段1:预热阶段
    - duration: 60
      arrivalRate: 10
      name: "Warmup Phase"
    
    # 阶段2:逐步施压
    - duration: 300
      arrivalRate: 50
      rampTo: 500
      name: "Stress Ramp-up"
    
    # 阶段3:极限压力
    - duration: 600
      arrivalRate: 1000
      name: "Peak Stress"
    
    # 阶段4:超限测试
    - duration: 300
      arrivalRate: 1000
      rampTo: 2000
      name: "Breaking Point Test"
    
    # 阶段5:恢复测试
    - duration: 180
      arrivalRate: 2000
      rampTo: 10
      name: "Recovery Phase"
  
  # 压力测试配置
  http:
    timeout: 30
    pool: 200  # 连接池大小
    maxSockets: 500
  
  # 插件配置
  plugins:
    metrics-by-endpoint: {}
    publish-metrics:
      - type: statsd
        host: localhost
        port: 8125
  
  # 测试数据生成
  variables:
    userId:
      - "{{ $randomInt(1, 10000) }}"
    requestId:
      - "{{ $uuid() }}"

scenarios:
  # 场景1:API密集调用
  - name: "API Intensive Load"
    weight: 40
    flow:
      - loop:
          - get:
              url: "/api/users/{{ $randomInt(1, 1000) }}"
              headers:
                X-Request-ID: "{{ requestId }}"
          - think: 0.1
          - post:
              url: "/api/analytics/events"
              json:
                userId: "{{ userId }}"
                eventType: "page_view"
                timestamp: "{{ $timestamp() }}"
          - think: 0.05
        count: 10
  
  # 场景2:数据库密集操作
  - name: "Database Intensive Operations"
    weight: 30
    flow:
      - post:
          url: "/api/orders"
          json:
            userId: "{{ userId }}"
            items:
              - productId: "{{ $randomInt(1, 100) }}"
                quantity: "{{ $randomInt(1, 5) }}"
            totalAmount: "{{ $randomFloat(10, 1000) }}"
      
      - get:
          url: "/api/orders/search"
          qs:
            userId: "{{ userId }}"
            status: "pending"
            limit: 50
      
      - put:
          url: "/api/orders/{{ $randomInt(1, 10000) }}"
          json:
            status: "processing"
            updatedAt: "{{ $timestamp() }}"
  
  # 场景3:文件上传压力
  - name: "File Upload Stress"
    weight: 20
    flow:
      - post:
          url: "/api/files/upload"
          beforeRequest: "generateLargePayload"
          json:
            filename: "test-{{ $randomString(10) }}.json"
            content: "{{ largeData }}"
            metadata:
              size: "{{ dataSize }}"
              type: "application/json"
  
  # 场景4:实时连接压力
  - name: "WebSocket Connection Stress"
    weight: 10
    flow:
      - function: "establishWebSocketConnection"
      - loop:
          - function: "sendWebSocketMessage"
          - think: 0.2
        count: 50
      - function: "closeWebSocketConnection"

# 自定义函数
functions:
  generateLargePayload:
    - set:
        dataSize: "{{ $randomInt(1000, 10000) }}"
        largeData: "{{ $randomString(dataSize) }}"
  
  establishWebSocketConnection:
    - log: "Establishing WebSocket connection"
  
  sendWebSocketMessage:
    - log: "Sending WebSocket message"
  
  closeWebSocketConnection:
    - log: "Closing WebSocket connection"

K6 极限压力测试

javascript
// k6-stress-test.js
import http from 'k6/http';
import ws from 'k6/ws';
import { check, group, sleep } from 'k6';
import { Rate, Trend, Counter, Gauge } from 'k6/metrics';

// 自定义指标
const errorRate = new Rate('error_rate');
const responseTime = new Trend('response_time');
const activeConnections = new Gauge('active_connections');
const memoryUsage = new Gauge('memory_usage');
const failedRequests = new Counter('failed_requests');

// 压力测试配置
export const options = {
  stages: [
    // 预热阶段
    { duration: '2m', target: 50 },
    
    // 压力爬升阶段
    { duration: '5m', target: 200 },
    { duration: '5m', target: 500 },
    { duration: '5m', target: 1000 },
    
    // 极限压力阶段
    { duration: '10m', target: 2000 },
    { duration: '5m', target: 3000 },
    
    // 破坏点测试
    { duration: '5m', target: 5000 },
    
    // 恢复阶段
    { duration: '5m', target: 1000 },
    { duration: '3m', target: 100 },
    { duration: '2m', target: 0 },
  ],
  
  thresholds: {
    // 压力测试的阈值更宽松
    http_req_duration: ['p(95)<5000', 'p(99)<10000'],
    http_req_failed: ['rate<0.1'],  // 允许10%的失败率
    error_rate: ['rate<0.15'],
    active_connections: ['value<6000'],
  },
  
  // 系统资源限制
  noConnectionReuse: false,
  userAgent: 'K6StressTest/1.0',
  insecureSkipTLSVerify: true,
  
  // 批量请求设置
  batch: 50,
  batchPerHost: 20,
};

const BASE_URL = 'http://localhost:3000';

// 测试数据生成器
function generateTestData() {
  return {
    userId: Math.floor(Math.random() * 10000),
    requestId: Math.random().toString(36).substring(7),
    timestamp: Date.now(),
    sessionId: Math.random().toString(36).substring(7)
  };
}

// 主测试函数
export default function() {
  const testData = generateTestData();
  
  group('API Stress Tests', () => {
    apiStressTest(testData);
  });
  
  group('Database Stress Tests', () => {
    databaseStressTest(testData);
  });
  
  group('Memory Stress Tests', () => {
    memoryStressTest(testData);
  });
  
  group('Concurrent Operations', () => {
    concurrentOperationsTest(testData);
  });
  
  // 很短的思考时间,增加压力
  sleep(Math.random() * 0.1);
}

function apiStressTest(testData) {
  // 并发API调用
  const responses = http.batch([
    ['GET', `${BASE_URL}/api/users/${testData.userId}`],
    ['GET', `${BASE_URL}/api/products/random`],
    ['GET', `${BASE_URL}/api/analytics/stats`],
    ['POST', `${BASE_URL}/api/events`, JSON.stringify({
      type: 'stress_test',
      userId: testData.userId,
      timestamp: testData.timestamp
    }), { headers: { 'Content-Type': 'application/json' } }]
  ]);
  
  responses.forEach((response, index) => {
    const success = check(response, {
      [`API call ${index} status ok`]: (r) => r.status < 400,
      [`API call ${index} response time ok`]: (r) => r.timings.duration < 5000,
    });
    
    if (!success) {
      failedRequests.add(1);
    }
    
    errorRate.add(!success);
    responseTime.add(response.timings.duration);
  });
}

function databaseStressTest(testData) {
  // 数据库密集操作
  const createResponse = http.post(`${BASE_URL}/api/stress-test/data`, JSON.stringify({
    userId: testData.userId,
    data: {
      // 生成大量数据
      items: Array.from({ length: 100 }, (_, i) => ({
        id: i,
        value: Math.random().toString(36).repeat(10),
        timestamp: Date.now()
      }))
    }
  }), {
    headers: { 'Content-Type': 'application/json' }
  });
  
  check(createResponse, {
    'database create status ok': (r) => r.status < 400,
    'database create time ok': (r) => r.timings.duration < 3000,
  });
  
  // 复杂查询操作
  const searchResponse = http.get(`${BASE_URL}/api/stress-test/search`, {
    params: {
      userId: testData.userId,
      limit: 100,
      sort: 'timestamp',
      filter: 'complex_query'
    }
  });
  
  check(searchResponse, {
    'database search status ok': (r) => r.status < 400,
    'database search time ok': (r) => r.timings.duration < 2000,
  });
  
  // 批量更新操作
  const updateResponse = http.put(`${BASE_URL}/api/stress-test/batch-update`, JSON.stringify({
    userIds: Array.from({ length: 50 }, () => Math.floor(Math.random() * 1000)),
    updateData: {
      lastActive: Date.now(),
      score: Math.floor(Math.random() * 100)
    }
  }), {
    headers: { 'Content-Type': 'application/json' }
  });
  
  check(updateResponse, {
    'batch update status ok': (r) => r.status < 400,
    'batch update time ok': (r) => r.timings.duration < 5000,
  });
}

function memoryStressTest(testData) {
  // 内存压力测试 - 大数据传输
  const largePayload = {
    userId: testData.userId,
    sessionId: testData.sessionId,
    data: Array.from({ length: 1000 }, (_, i) => ({
      id: i,
      content: 'x'.repeat(1000), // 1KB per item
      metadata: {
        created: Date.now(),
        hash: Math.random().toString(36),
        tags: Array.from({ length: 10 }, () => Math.random().toString(36))
      }
    }))
  };
  
  const response = http.post(`${BASE_URL}/api/stress-test/large-data`, JSON.stringify(largePayload), {
    headers: { 'Content-Type': 'application/json' },
    timeout: '30s'
  });
  
  const success = check(response, {
    'large data upload status ok': (r) => r.status < 400,
    'large data upload time ok': (r) => r.timings.duration < 10000,
    'response size reasonable': (r) => r.body.length < 100000,
  });
  
  if (!success) {
    failedRequests.add(1);
  }
  
  // 检查服务器内存使用情况
  const healthResponse = http.get(`${BASE_URL}/health/memory`);
  if (healthResponse.status === 200) {
    try {
      const healthData = JSON.parse(healthResponse.body);
      memoryUsage.add(healthData.memoryUsage || 0);
    } catch (e) {
      // 忽略解析错误
    }
  }
}

function concurrentOperationsTest(testData) {
  // 并发操作压力测试
  const concurrentRequests = [];
  
  // 创建大量并发请求
  for (let i = 0; i < 20; i++) {
    concurrentRequests.push([
      'POST',
      `${BASE_URL}/api/stress-test/concurrent`,
      JSON.stringify({
        operationId: `${testData.sessionId}-${i}`,
        userId: testData.userId,
        data: Math.random().toString(36).repeat(100)
      }),
      { headers: { 'Content-Type': 'application/json' } }
    ]);
  }
  
  const startTime = Date.now();
  const responses = http.batch(concurrentRequests);
  const endTime = Date.now();
  
  activeConnections.add(responses.length);
  
  let successCount = 0;
  responses.forEach((response, index) => {
    const success = check(response, {
      [`concurrent operation ${index} success`]: (r) => r.status < 400,
    });
    
    if (success) {
      successCount++;
    }
  });
  
  check({ successCount, total: responses.length }, {
    'concurrent operations success rate > 80%': (data) => (data.successCount / data.total) > 0.8,
    'concurrent operations completed in reasonable time': () => (endTime - startTime) < 5000,
  });
}

// WebSocket压力测试
export function websocketStressTest() {
  const url = 'ws://localhost:3000/ws';
  const params = { tags: { name: 'WebSocketStress' } };
  
  const response = ws.connect(url, params, function (socket) {
    socket.on('open', () => {
      console.log('WebSocket connection opened');
      
      // 发送大量消息
      for (let i = 0; i < 100; i++) {
        socket.send(JSON.stringify({
          type: 'stress_message',
          id: i,
          data: 'x'.repeat(1000), // 1KB message
          timestamp: Date.now()
        }));
      }
    });
    
    socket.on('message', (data) => {
      check(data, {
        'message received': (msg) => msg.length > 0,
      });
    });
    
    socket.on('error', (e) => {
      console.log('WebSocket error:', e.error());
      failedRequests.add(1);
    });
    
    // 保持连接一段时间
    sleep(10);
  });
  
  check(response, {
    'websocket connection established': (r) => r && r.status === 101,
  });
}

// 测试设置
export function setup() {
  console.log('Starting stress test setup...');
  
  // 预热服务器
  const warmupResponse = http.get(`${BASE_URL}/health`);
  if (warmupResponse.status !== 200) {
    throw new Error('Server is not available for stress testing');
  }
  
  console.log('Stress test setup completed');
  return { baseUrl: BASE_URL };
}

// 测试清理
export function teardown(data) {
  console.log('Stress test completed');
  console.log(`Target URL: ${data.baseUrl}`);
  
  // 获取最终的健康状态
  const finalHealth = http.get(`${data.baseUrl}/health`);
  console.log(`Final server status: ${finalHealth.status}`);
}

Node.js 内存压力测试

javascript
// memory-stress-test.js
const { Worker, isMainThread, parentPort, workerData } = require('worker_threads');
const v8 = require('v8');
const fs = require('fs');

class MemoryStressTest {
  constructor() {
    this.workers = [];
    this.memoryLeaks = [];
    this.results = {
      initialMemory: process.memoryUsage(),
      peakMemory: process.memoryUsage(),
      finalMemory: null,
      gcStats: [],
      errors: []
    };
  }
  
  // 启动内存压力测试
  async runMemoryStressTest(options = {}) {
    const {
      duration = 60000,        // 测试持续时间
      workerCount = 4,         // 工作线程数
      memoryPressure = 'high', // 内存压力级别
      gcMonitoring = true      // 是否监控GC
    } = options;
    
    console.log(`🚀 Starting memory stress test for ${duration}ms`);
    
    if (gcMonitoring) {
      this.startGCMonitoring();
    }
    
    // 启动内存压力监控
    const memoryMonitor = this.startMemoryMonitoring();
    
    try {
      // 启动工作线程
      await this.startWorkers(workerCount, memoryPressure);
      
      // 主线程内存压力
      await this.mainThreadMemoryStress(duration);
      
      // 等待测试完成
      await new Promise(resolve => setTimeout(resolve, duration));
      
    } finally {
      // 清理资源
      await this.cleanup();
      clearInterval(memoryMonitor);
      
      this.results.finalMemory = process.memoryUsage();
    }
    
    return this.generateMemoryReport();
  }
  
  // 启动工作线程
  async startWorkers(count, pressureLevel) {
    const workerPromises = [];
    
    for (let i = 0; i < count; i++) {
      const workerPromise = new Promise((resolve, reject) => {
        const worker = new Worker(__filename, {
          workerData: { 
            workerId: i, 
            pressureLevel,
            isWorker: true 
          }
        });
        
        worker.on('message', (message) => {
          if (message.type === 'memory_stats') {
            this.updateMemoryStats(message.data);
          }
        });
        
        worker.on('error', (error) => {
          this.results.errors.push({
            worker: i,
            error: error.message,
            timestamp: Date.now()
          });
          reject(error);
        });
        
        worker.on('exit', (code) => {
          if (code !== 0) {
            this.results.errors.push({
              worker: i,
              error: `Worker exited with code ${code}`,
              timestamp: Date.now()
            });
          }
          resolve();
        });
        
        this.workers.push(worker);
      });
      
      workerPromises.push(workerPromise);
    }
    
    return Promise.allSettled(workerPromises);
  }
  
  // 主线程内存压力
  async mainThreadMemoryStress(duration) {
    const startTime = Date.now();
    const chunks = [];
    
    const stressInterval = setInterval(() => {
      try {
        // 创建大量对象
        for (let i = 0; i < 1000; i++) {
          chunks.push({
            id: i,
            data: Buffer.alloc(1024), // 1KB buffer
            timestamp: Date.now(),
            metadata: {
              created: new Date(),
              random: Math.random().toString(36).repeat(100)
            }
          });
        }
        
        // 偶尔清理一些对象,模拟真实场景
        if (chunks.length > 10000) {
          chunks.splice(0, 5000);
        }
        
        // 创建内存泄漏(故意的,用于测试)
        this.memoryLeaks.push({
          largeArray: new Array(1000).fill(Math.random().toString(36)),
          circularRef: null
        });
        
        // 创建循环引用
        const last = this.memoryLeaks[this.memoryLeaks.length - 1];
        last.circularRef = last;
        
      } catch (error) {
        this.results.errors.push({
          source: 'main_thread',
          error: error.message,
          timestamp: Date.now()
        });
      }
    }, 10);
    
    // 清理定时器
    setTimeout(() => {
      clearInterval(stressInterval);
    }, duration);
  }
  
  // 启动内存监控
  startMemoryMonitoring() {
    return setInterval(() => {
      const currentMemory = process.memoryUsage();
      const heapStats = v8.getHeapStatistics();
      
      // 更新峰值内存
      if (currentMemory.heapUsed > this.results.peakMemory.heapUsed) {
        this.results.peakMemory = currentMemory;
      }
      
      // 记录内存统计
      this.results.memoryStats = this.results.memoryStats || [];
      this.results.memoryStats.push({
        timestamp: Date.now(),
        memory: currentMemory,
        heap: {
          totalHeapSize: heapStats.total_heap_size,
          usedHeapSize: heapStats.used_heap_size,
          heapSizeLimit: heapStats.heap_size_limit
        }
      });
      
      // 检查内存使用是否过高
      const memoryUsagePercent = (currentMemory.heapUsed / heapStats.heap_size_limit) * 100;
      if (memoryUsagePercent > 80) {
        console.warn(`⚠️  High memory usage: ${memoryUsagePercent.toFixed(1)}%`);
      }
      
    }, 1000);
  }
  
  // 启动GC监控
  startGCMonitoring() {
    // V8 GC性能监控
    const obs = new PerformanceObserver((list) => {
      const entries = list.getEntries();
      entries.forEach((entry) => {
        this.results.gcStats.push({
          type: entry.name,
          duration: entry.duration,
          timestamp: Date.now()
        });
      });
    });
    
    obs.observe({ entryTypes: ['gc'] });
  }
  
  // 更新内存统计
  updateMemoryStats(stats) {
    this.results.workerStats = this.results.workerStats || [];
    this.results.workerStats.push(stats);
  }
  
  // 清理资源
  async cleanup() {
    // 终止所有工作线程
    for (const worker of this.workers) {
      await worker.terminate();
    }
    
    this.workers = [];
    
    // 清理内存泄漏对象
    this.memoryLeaks = [];
    
    // 强制垃圾回收
    if (global.gc) {
      global.gc();
    }
  }
  
  // 生成内存压力测试报告
  generateMemoryReport() {
    const initialMem = this.results.initialMemory;
    const peakMem = this.results.peakMemory;
    const finalMem = this.results.finalMemory;
    
    const report = {
      summary: {
        initialHeapUsed: `${Math.round(initialMem.heapUsed / 1024 / 1024)}MB`,
        peakHeapUsed: `${Math.round(peakMem.heapUsed / 1024 / 1024)}MB`,
        finalHeapUsed: `${Math.round(finalMem.heapUsed / 1024 / 1024)}MB`,
        heapGrowth: `${Math.round((peakMem.heapUsed - initialMem.heapUsed) / 1024 / 1024)}MB`,
        gcCount: this.results.gcStats.length,
        errorCount: this.results.errors.length
      },
      
      analysis: this.analyzeMemoryBehavior(),
      recommendations: this.generateMemoryRecommendations(),
      
      detailedStats: {
        gcStats: this.results.gcStats,
        memoryStats: this.results.memoryStats?.slice(-10), // 最后10个数据点
        errors: this.results.errors
      }
    };
    
    console.log('📊 Memory Stress Test Report:');
    console.log(`Initial Heap: ${report.summary.initialHeapUsed}`);
    console.log(`Peak Heap: ${report.summary.peakHeapUsed}`);
    console.log(`Final Heap: ${report.summary.finalHeapUsed}`);
    console.log(`Heap Growth: ${report.summary.heapGrowth}`);
    console.log(`GC Count: ${report.summary.gcCount}`);
    console.log(`Errors: ${report.summary.errorCount}`);
    
    return report;
  }
  
  // 分析内存行为
  analyzeMemoryBehavior() {
    const gcStats = this.results.gcStats;
    const memoryStats = this.results.memoryStats || [];
    
    const analysis = {
      memoryLeakDetected: false,
      gcPerformance: 'unknown',
      memoryEfficiency: 'unknown'
    };
    
    // 检测内存泄漏
    if (memoryStats.length > 10) {
      const recentStats = memoryStats.slice(-10);
      const memoryTrend = recentStats.map(s => s.memory.heapUsed);
      const isIncreasing = memoryTrend.every((val, i, arr) => 
        i === 0 || val >= arr[i-1]
      );
      
      analysis.memoryLeakDetected = isIncreasing;
    }
    
    // 分析GC性能
    if (gcStats.length > 0) {
      const avgGCDuration = gcStats.reduce((sum, gc) => sum + gc.duration, 0) / gcStats.length;
      
      if (avgGCDuration < 10) {
        analysis.gcPerformance = 'excellent';
      } else if (avgGCDuration < 50) {
        analysis.gcPerformance = 'good';
      } else if (avgGCDuration < 100) {
        analysis.gcPerformance = 'fair';
      } else {
        analysis.gcPerformance = 'poor';
      }
    }
    
    return analysis;
  }
  
  // 生成内存优化建议
  generateMemoryRecommendations() {
    const recommendations = [];
    const analysis = this.analyzeMemoryBehavior();
    
    if (analysis.memoryLeakDetected) {
      recommendations.push({
        priority: 'HIGH',
        category: 'Memory Leak',
        message: '检测到潜在内存泄漏,建议检查循环引用和事件监听器清理'
      });
    }
    
    if (analysis.gcPerformance === 'poor') {
      recommendations.push({
        priority: 'HIGH',
        category: 'GC Performance',
        message: 'GC性能较差,建议优化对象创建和生命周期管理'
      });
    }
    
    if (this.results.errors.length > 0) {
      recommendations.push({
        priority: 'MEDIUM',
        category: 'Error Handling',
        message: `发现${this.results.errors.length}个错误,需要检查错误处理机制`
      });
    }
    
    const peakMemoryMB = this.results.peakMemory.heapUsed / 1024 / 1024;
    if (peakMemoryMB > 500) {
      recommendations.push({
        priority: 'MEDIUM',
        category: 'Memory Usage',
        message: `峰值内存使用${Math.round(peakMemoryMB)}MB,考虑内存优化`
      });
    }
    
    return recommendations;
  }
}

// 工作线程代码
if (!isMainThread && workerData.isWorker) {
  const { workerId, pressureLevel } = workerData;
  
  console.log(`Worker ${workerId} started with pressure level: ${pressureLevel}`);
  
  // 工作线程内存压力函数
  function workerMemoryStress() {
    const objects = [];
    
    const stressInterval = setInterval(() => {
      try {
        // 根据压力级别创建不同数量的对象
        const objectCount = pressureLevel === 'high' ? 5000 : 
                           pressureLevel === 'medium' ? 2000 : 1000;
        
        for (let i = 0; i < objectCount; i++) {
          objects.push({
            id: `worker-${workerId}-${i}`,
            data: new Array(100).fill(Math.random()),
            timestamp: Date.now()
          });
        }
        
        // 定期清理对象,避免无限增长
        if (objects.length > 50000) {
          objects.splice(0, 25000);
        }
        
        // 发送内存统计
        const memUsage = process.memoryUsage();
        parentPort.postMessage({
          type: 'memory_stats',
          data: {
            workerId,
            memoryUsage: memUsage,
            objectCount: objects.length,
            timestamp: Date.now()
          }
        });
        
      } catch (error) {
        parentPort.postMessage({
          type: 'error',
          data: {
            workerId,
            error: error.message,
            timestamp: Date.now()
          }
        });
      }
    }, 100);
    
    // 10分钟后停止
    setTimeout(() => {
      clearInterval(stressInterval);
      process.exit(0);
    }, 600000);
  }
  
  workerMemoryStress();
}

module.exports = MemoryStressTest;

🔧 压力测试场景设计

真实业务场景压力测试

javascript
// real-world-stress-scenarios.js
const axios = require('axios');

class RealWorldStressScenarios {
  constructor(baseUrl = 'http://localhost:3000') {
    this.baseUrl = baseUrl;
    this.activeUsers = new Map();
    this.results = {
      scenarios: [],
      errors: [],
      metrics: {}
    };
  }
  
  // 电商促销场景压力测试
  async ecommerceFlashSaleStress(options = {}) {
    const {
      duration = 300000,      // 5分钟
      peakConcurrency = 5000, // 峰值并发
      productCount = 100      // 参与促销的商品数
    } = options;
    
    console.log('🛒 Starting e-commerce flash sale stress test...');
    
    const scenario = {
      name: 'E-commerce Flash Sale',
      startTime: Date.now(),
      duration,
      peakConcurrency,
      phases: []
    };
    
    try {
      // 阶段1:预热 - 正常访问
      await this.runPhase('预热阶段', 60000, 100, () => 
        this.simulateNormalBrowsing()
      );
      
      // 阶段2:促销开始前 - 用户聚集
      await this.runPhase('用户聚集', 60000, 1000, () => 
        this.simulateUserWaiting()
      );
      
      // 阶段3:促销开始 - 极限并发
      await this.runPhase('促销高峰', 120000, peakConcurrency, () => 
        this.simulateFlashSale(productCount)
      );
      
      // 阶段4:促销后期 - 逐渐下降
      await this.runPhase('流量下降', 60000, 500, () => 
        this.simulateNormalBrowsing()
      );
      
      scenario.endTime = Date.now();
      scenario.success = true;
      
    } catch (error) {
      scenario.error = error.message;
      scenario.success = false;
    }
    
    this.results.scenarios.push(scenario);
    return scenario;
  }
  
  // 社交媒体病毒传播场景
  async socialMediaViralStress(options = {}) {
    const {
      duration = 600000,      // 10分钟
      initialUsers = 100,     // 初始用户数
      viralFactor = 2,        // 病毒传播系数
      peakMultiplier = 50     // 峰值倍数
    } = options;
    
    console.log('📱 Starting social media viral content stress test...');
    
    const scenario = {
      name: 'Social Media Viral Content',
      startTime: Date.now(),
      duration,
      phases: []
    };
    
    try {
      let currentUsers = initialUsers;
      const phaseCount = 6;
      const phaseDuration = duration / phaseCount;
      
      for (let phase = 1; phase <= phaseCount; phase++) {
        const phaseName = `病毒传播阶段${phase}`;
        
        await this.runPhase(phaseName, phaseDuration, currentUsers, () =>
          this.simulateViralContent()
        );
        
        // 指数增长模拟
        currentUsers = Math.min(
          Math.floor(currentUsers * viralFactor),
          initialUsers * peakMultiplier
        );
        
        scenario.phases.push({
          phase,
          userCount: currentUsers,
          timestamp: Date.now()
        });
      }
      
      scenario.success = true;
      
    } catch (error) {
      scenario.error = error.message;
      scenario.success = false;
    }
    
    this.results.scenarios.push(scenario);
    return scenario;
  }
  
  // 金融交易高峰场景
  async financialTradingRushStress(options = {}) {
    const {
      duration = 300000,      // 5分钟
      traderCount = 2000,     // 交易员数量
      transactionRate = 100   // 每秒交易数
    } = options;
    
    console.log('💰 Starting financial trading rush stress test...');
    
    const scenario = {
      name: 'Financial Trading Rush',
      startTime: Date.now(),
      duration,
      traderCount,
      transactionRate
    };
    
    try {
      // 模拟市场开盘时的交易高峰
      await Promise.all([
        // 高频交易
        this.runContinuousLoad(duration, traderCount * 0.3, () =>
          this.simulateHighFrequencyTrading()
        ),
        
        // 普通交易
        this.runContinuousLoad(duration, traderCount * 0.5, () =>
          this.simulateRegularTrading()
        ),
        
        // 市场数据查询
        this.runContinuousLoad(duration, traderCount, () =>
          this.simulateMarketDataQuery()
        ),
        
        // 风险管理系统
        this.runContinuousLoad(duration, 50, () =>
          this.simulateRiskManagement()
        )
      ]);
      
      scenario.success = true;
      
    } catch (error) {
      scenario.error = error.message;
      scenario.success = false;
    }
    
    this.results.scenarios.push(scenario);
    return scenario;
  }
  
  // 运行测试阶段
  async runPhase(phaseName, duration, concurrency, testFunction) {
    console.log(`  📊 ${phaseName}: ${concurrency} concurrent users for ${duration}ms`);
    
    const startTime = Date.now();
    const promises = [];
    
    // 创建并发用户
    for (let i = 0; i < concurrency; i++) {
      promises.push(this.simulateUser(i, duration, testFunction));
    }
    
    // 等待所有用户完成或阶段结束
    await Promise.race([
      Promise.allSettled(promises),
      new Promise(resolve => setTimeout(resolve, duration))
    ]);
    
    const endTime = Date.now();
    console.log(`  ✅ ${phaseName} completed in ${endTime - startTime}ms`);
  }
  
  // 连续负载测试
  async runContinuousLoad(duration, concurrency, testFunction) {
    const endTime = Date.now() + duration;
    const promises = [];
    
    while (Date.now() < endTime) {
      // 批量创建用户会话
      const batchSize = Math.min(concurrency, 100);
      
      for (let i = 0; i < batchSize; i++) {
        promises.push(testFunction());
      }
      
      // 等待一小段时间再创建下一批
      await new Promise(resolve => setTimeout(resolve, 100));
      
      // 清理已完成的promise
      const settled = promises.splice(0, Math.floor(promises.length / 2));
      await Promise.allSettled(settled);
    }
    
    // 等待剩余的promise完成
    await Promise.allSettled(promises);
  }
  
  // 模拟用户行为
  async simulateUser(userId, duration, testFunction) {
    const endTime = Date.now() + duration;
    const userSession = {
      id: userId,
      startTime: Date.now(),
      actions: 0,
      errors: 0
    };
    
    this.activeUsers.set(userId, userSession);
    
    try {
      while (Date.now() < endTime) {
        await testFunction();
        userSession.actions++;
        
        // 随机思考时间
        await new Promise(resolve => 
          setTimeout(resolve, Math.random() * 1000)
        );
      }
    } catch (error) {
      userSession.errors++;
      this.results.errors.push({
        userId,
        error: error.message,
        timestamp: Date.now()
      });
    } finally {
      userSession.endTime = Date.now();
      this.activeUsers.delete(userId);
    }
  }
  
  // 业务场景模拟函数
  async simulateNormalBrowsing() {
    const actions = [
      () => axios.get(`${this.baseUrl}/api/products/featured`),
      () => axios.get(`${this.baseUrl}/api/categories`),
      () => axios.get(`${this.baseUrl}/api/products/${Math.floor(Math.random() * 1000)}`),
      () => axios.get(`${this.baseUrl}/api/reviews/latest`)
    ];
    
    const action = actions[Math.floor(Math.random() * actions.length)];
    await action();
  }
  
  async simulateUserWaiting() {
    // 用户等待促销开始,频繁刷新页面
    await Promise.all([
      axios.get(`${this.baseUrl}/api/flash-sale/status`),
      axios.get(`${this.baseUrl}/api/flash-sale/countdown`),
      axios.get(`${this.baseUrl}/api/flash-sale/products`)
    ]);
  }
  
  async simulateFlashSale(productCount) {
    const productId = Math.floor(Math.random() * productCount) + 1;
    
    try {
      // 高频刷新商品信息
      await axios.get(`${this.baseUrl}/api/flash-sale/products/${productId}`);
      
      // 尝试加入购物车
      await axios.post(`${this.baseUrl}/api/cart/add`, {
        productId,
        quantity: 1
      });
      
      // 尝试结账
      await axios.post(`${this.baseUrl}/api/orders/checkout`, {
        cartId: `cart-${Date.now()}`
      });
      
    } catch (error) {
      // 促销商品可能已售罄,这是正常的
      if (!error.response || error.response.status !== 409) {
        throw error;
      }
    }
  }
  
  async simulateViralContent() {
    const contentId = Math.floor(Math.random() * 10) + 1;
    
    await Promise.all([
      axios.get(`${this.baseUrl}/api/content/${contentId}`),
      axios.post(`${this.baseUrl}/api/content/${contentId}/view`),
      axios.get(`${this.baseUrl}/api/content/${contentId}/comments`),
      // 随机分享行为
      Math.random() > 0.7 ? axios.post(`${this.baseUrl}/api/content/${contentId}/share`) : Promise.resolve()
    ]);
  }
  
  async simulateHighFrequencyTrading() {
    const symbol = ['AAPL', 'GOOGL', 'MSFT', 'AMZN'][Math.floor(Math.random() * 4)];
    
    await Promise.all([
      axios.get(`${this.baseUrl}/api/market/quote/${symbol}`),
      axios.post(`${this.baseUrl}/api/trading/orders`, {
        symbol,
        type: 'market',
        side: Math.random() > 0.5 ? 'buy' : 'sell',
        quantity: Math.floor(Math.random() * 100) + 1
      })
    ]);
  }
  
  async simulateRegularTrading() {
    const actions = [
      () => axios.get(`${this.baseUrl}/api/portfolio/positions`),
      () => axios.get(`${this.baseUrl}/api/market/watchlist`),
      () => axios.get(`${this.baseUrl}/api/trading/history`),
      () => axios.post(`${this.baseUrl}/api/trading/orders`, {
        symbol: 'SPY',
        type: 'limit',
        side: 'buy',
        quantity: 10,
        price: 450.00
      })
    ];
    
    const action = actions[Math.floor(Math.random() * actions.length)];
    await action();
  }
  
  async simulateMarketDataQuery() {
    await axios.get(`${this.baseUrl}/api/market/realtime-data`);
  }
  
  async simulateRiskManagement() {
    await Promise.all([
      axios.get(`${this.baseUrl}/api/risk/portfolio-analysis`),
      axios.get(`${this.baseUrl}/api/risk/exposure-limits`),
      axios.post(`${this.baseUrl}/api/risk/calculate-var`)
    ]);
  }
  
  // 生成压力测试报告
  generateStressReport() {
    const report = {
      summary: {
        totalScenarios: this.results.scenarios.length,
        successfulScenarios: this.results.scenarios.filter(s => s.success).length,
        totalErrors: this.results.errors.length,
        testDuration: this.results.scenarios.reduce((sum, s) => sum + (s.duration || 0), 0)
      },
      
      scenarios: this.results.scenarios.map(scenario => ({
        name: scenario.name,
        success: scenario.success,
        duration: scenario.duration,
        phases: scenario.phases?.length || 0,
        error: scenario.error
      })),
      
      errorAnalysis: this.analyzeErrors(),
      recommendations: this.generateStressRecommendations()
    };
    
    console.log('📊 Stress Test Report:');
    console.log(`Scenarios: ${report.summary.successfulScenarios}/${report.summary.totalScenarios} successful`);
    console.log(`Total Errors: ${report.summary.totalErrors}`);
    
    return report;
  }
  
  analyzeErrors() {
    const errorsByType = {};
    
    this.results.errors.forEach(error => {
      const errorType = error.error.split(':')[0];
      errorsByType[errorType] = (errorsByType[errorType] || 0) + 1;
    });
    
    return errorsByType;
  }
  
  generateStressRecommendations() {
    const recommendations = [];
    
    if (this.results.errors.length > 100) {
      recommendations.push({
        priority: 'HIGH',
        category: 'Error Rate',
        message: `错误数量过高(${this.results.errors.length}),需要检查系统稳定性`
      });
    }
    
    const failedScenarios = this.results.scenarios.filter(s => !s.success);
    if (failedScenarios.length > 0) {
      recommendations.push({
        priority: 'HIGH',
        category: 'Scenario Failure',
        message: `${failedScenarios.length}个场景失败,需要检查系统承载能力`
      });
    }
    
    return recommendations;
  }
}

module.exports = RealWorldStressScenarios;

📝 压力测试最佳实践

环境准备和监控

javascript
const StressTestingBestPractices = {
  ENVIRONMENT_PREPARATION: {
    infrastructure: [
      '使用与生产环境相同的硬件配置',
      '确保网络环境稳定可靠',
      '准备充足的测试数据',
      '配置完整的监控系统'
    ],
    
    baseline: [
      '建立性能基线指标',
      '记录正常负载下的表现',
      '确定关键性能指标',
      '设置监控告警阈值'
    ]
  },
  
  TEST_EXECUTION: {
    gradualApproach: [
      '逐步增加负载强度',
      '观察系统行为变化',
      '识别第一个瓶颈点',
      '记录关键转折点'
    ],
    
    monitoring: [
      '实时监控系统资源',
      '记录详细的性能指标',
      '捕获系统错误和异常',
      '分析用户体验影响'
    ],
    
    safety: [
      '设置安全阈值',
      '准备紧急停止机制',
      '确保数据安全',
      '建立快速恢复流程'
    ]
  },
  
  RESULT_ANALYSIS: {
    metrics: [
      '分析响应时间分布',
      '计算错误率趋势',
      '评估资源利用率',
      '识别性能瓶颈'
    ],
    
    patterns: [
      '观察系统降级模式',
      '分析故障传播路径',
      '评估恢复能力',
      '总结优化建议'
    ]
  }
};

📝 总结

压力测试是验证系统极限承载能力的重要手段:

  • 破坏点发现:找出系统在极限条件下的失效点
  • 稳定性验证:验证系统在高压下的稳定性
  • 恢复能力评估:测试系统从压力状态的恢复能力
  • 性能优化指导:为系统优化提供数据支持

通过系统化的压力测试,可以确保Node.js应用在极端条件下的可靠性和用户体验。

🔗 相关资源