性能压测负载测试k6Locust

AI API 性能压测与负载测试实战指南:把 P95 延迟和吞吐量测准

2026-09-04 · 约 12 分钟阅读

选 AI API 中转站的时候,营销页都写着"超快""毫秒级""高并发"。但没有真实压测数据的性能对比都是耍流氓。本文是一篇纯方法论的压测指南,教你用 k6 / Locust 等开源工具自己跑一遍压测,得出可信的 P50/P95/P99 延迟、TPS、错误率等核心指标。

一、AI API 压测和传统 Web 压测的差异

AI API 不能套用普通 HTTP 服务的压测套路,主要有 3 个差异点:

维度普通 Web 服务AI API
响应模型同步、快(< 200ms)流式、慢(首字 300-1500ms)
单次成本几乎为零真实花美元($0.0001 - $0.05)
输出长度固定(几十字节)不可预测(几 token 到几万 token)
限速维度QPSQPS + TPM(每分钟 token 数)

所以压测时必须关注三个 AI 特有的指标:

1. TTFT(Time To First Token):首字延迟,决定用户主观体验

2. ITL(Inter-Token Latency):块间延迟,决定输出流畅度

3. TPS(Tokens Per Second):吞吐能力,决定并发上限

二、压测工具选型

工具语言优势适合场景
k6Go脚本化、CI 友好、生态成熟持续性能测试、回归压测
LocustPython代码灵活、易扩展复杂业务流、自定义负载模式
vegetaGo单二进制、命令行快速冒烟、基线对比
wrkC极致性能、低开销纯吞吐量基线(不擅长流式)
heyGo单文件、零依赖一行命令快速摸底

对 AI API 压测来说,k6 + Locust 组合最实用:k6 做基线和 CI,Locust 做复杂场景模拟。

三、k6 实战:压测 OpenAI 兼容接口

// loadtest.js
import http from 'k6/http';
import { check, sleep } from 'k6';
import { Trend } from 'k6/metrics';

const ttft = new Trend('ttft_ms');      // 首字延迟
const itl = new Trend('itl_ms');        // 块间延迟
const total = new Trend('total_ms');    // 总延迟

export const options = {
  stages: [
    { duration: '30s', target: 10 },    // 预热
    { duration: '2m',  target: 50 },    // 逐步加压到 50 并发
    { duration: '3m',  target: 50 },    // 持续 50 并发 3 分钟
    { duration: '30s', target: 0 },     // 退压
  ],
  thresholds: {
    'ttft_ms': ['p(95)<1000'],         // 95% 请求 TTFT < 1s
    'http_req_failed': ['rate<0.01'],  // 错误率 < 1%
  },
};

export default function () {
  const payload = JSON.stringify({
    model: 'gpt-4o',
    messages: [{ role: 'user', content: '写一首关于秋天的五言绝句' }],
    stream: true,
    max_tokens: 200,
  });

  const params = {
    headers: {
      'Content-Type': 'application/json',
      'Authorization': `Bearer ${__ENV.API_KEY}`,
    },
  };

  const start = Date.now();
  let firstByteAt = null;
  let prevChunkAt = null;
  let chunkCount = 0;

  const res = http.post(
    `${__ENV.BASE_URL}/chat/completions`,
    payload,
    params,
  );

  // 注:k6 原生 http.post 不直接支持流式分块计时
  // 流式压测需要用 http.send + 自定义解析,或扩展 k6
  // 下面先做非流式基线测
  if (res.status === 200) {
    total.add(Date.now() - start);
    ttft.add(Date.now() - start); // 非流式 = 全部延迟
  }

  check(res, {
    'status is 200': (r) => r.status === 200,
  });

  sleep(1);
}

重要警告:上面的脚本只压了非流式场景。要测真实的流式 TTFT/ITL,必须使用支持 SSE 解析的扩展或更上层的工具。

四、Locust 实战:流式 TTFT/ITL 精细测量

Locust 的 Python 灵活性让它更适合 AI 流式压测:

# locustfile.py
import time
import gevent
from locust import HttpUser, task, between
import sseclient  # pip install sseclient-py

class AIUser(HttpUser):
    wait_time = between(0.5, 2)
    host = "https://api.openai.com"  # 或中转站域名

    @task
    def chat_stream(self):
        payload = {
            "model": "gpt-4o",
            "messages": [{"role": "user", "content": "写一首五言绝句"}],
            "stream": True,
            "max_tokens": 100,
        }
        headers = {
            "Authorization": f"Bearer {self.environment.parsed_options.api_key}",
            "Content-Type": "application/json",
        }

        start = time.perf_counter()
        ttft = None
        itl_samples = []
        chunk_count = 0
        prev_ts = None

        with self.client.post(
            "/v1/chat/completions",
            json=payload,
            headers=headers,
            stream=True,
            catch_response=True,
        ) as response:
            if response.status_code != 200:
                response.failure(f"status {response.status_code}")
                return

            client = sseclient.SSEClient(response.iter_lines())
            for event in client.events():
                now = time.perf_counter()
                chunk_count += 1
                if ttft is None:
                    ttft = (now - start) * 1000
                else:
                    itl_samples.append((now - prev_ts) * 1000)
                prev_ts = now

            total_ms = (time.perf_counter() - start) * 1000

            # 上报指标
            self.environment.events.request.fire(
                request_type="POST",
                name="chat/ttft",
                response_time=ttft,
                response_length=0,
                exception=None,
                context={},
            )
            self.environment.events.request.fire(
                request_type="POST",
                name="chat/itl_p95",
                response_time=sorted(itl_samples)[int(len(itl_samples)*0.95)] if itl_samples else 0,
                response_length=0,
                exception=None,
                context={},
            )

            response.success()

然后启动:

locust -f locustfile.py --users 50 --spawn-rate 5 --run-time 5m \
       --host https://api.openai.com

五、压测的 5 个核心指标

跑完压测后,重点关注这 5 类指标:

指标含义健康阈值(参考)
TTFT P9595% 请求的首字延迟< 1000ms
ITL P9595% 块间延迟< 80ms
TPS单请求平均吞吐> 30 tokens/s
错误率4xx/5xx 占比< 1%
TPM 上限触顶时的稳定 TPM决定并发上限

注意:压测时不要压到"触顶就报错"的程度,真正的上限是"开始降速但还能返回正确结果"的拐点。

六、可重复压测的关键要素

要做出可对比的压测结果,变量控制是关键:

1. 固定 prompt 模板:每次压测用完全相同的 prompt(避免模型回复长度变化影响 TPS)

2. 固定时间窗口:在每天固定时段压(如凌晨 2-5 点,供应商低峰)

3. 多轮对比:同一时段对 A、B、C 三家各跑 3 轮取中位数

4. 冷热分别测:分"冷启动(key 首次调用)"和"热运行(已 warmed up)"两种状态

5. 记录供应商公告:压测期间任何公告(如"我们正在维护")都可能让结果失真

七、不同场景的负载模型

不同业务要模拟不同负载:

业务并发模型Prompt 长度期望输出长度
聊天助手5-20 并发 / 用户短(200-1000 token)中(200-800 token)
批量文档处理50-200 并发长(5K-50K token)短(100-500 token)
实时语音转写20-50 流式长连接流式音频 chunk流式文本 chunk
代码生成 Agent5-10 并发 / 用户(高 reasoning)中(2K-10K)长(500-3000)
图像生成1-3 并发 / 用户短文本长等待(10-30s)

聊天助手类负载最容易压,但要关注"长上下文场景"——Prompt 超过 50K 后 TTFT 通常 ×2。

八、压测的 3 个常见误区

1. "压到底"才算数:压到 5xx 错误率高不代表上限,因为正常业务不会跑到那个点

2. "只跑一次"就下结论:AI 服务有明显时段波动,单次结果波动可达 30%

3. "忽略限速":压测期间可能瞬间吃掉供应商一整天的配额,先用低配额测,确认 OK 后再放大

九、用压测数据横向对比中转站

如果你想横向对比各家 AI API 中转站,自建压测数据比看厂商宣传页可靠得多。一个对比表格应该长这样:

平台模型TTFT P95ITL P95TPSTPM 上限备注
平台 Agpt-4o850ms65ms45180K表现稳定
平台 Bgpt-4o720ms55ms52200K最快
平台 Cgpt-4o1500ms80ms30100K偶发超时

这种表格的数据应当来自你自己的真实压测。如果你懒得自己压,openairouter.net 上也整理了主流中转站的横向对比数据,可以作为初步参考。

十、压测数据的归档与可视化

跑出来的原始数据要归档,便于后续分析:

# k6 输出 JSON
k6 run --out json=results.json loadtest.js

# Locust 输出 CSV(用 --csv 开启)
locust -f locustfile.py --csv=run_$(date +%Y%m%d_%H%M)

建议把每天的压测结果入库(ClickHouse / TimescaleDB),用 Grafana 看板做长期趋势可视化——你就能发现"哪家供应商最近在变慢"。

总结

AI API 性能压测不是"发请求看响应时间"那么简单。它需要分清 TTFT / ITL / TPS 三个指标、固定变量、设计合理的负载模型、用合适的工具(k6 + Locust)、做可重复的对比实验。这套方法论搭起来后,你就能摆脱营销页的忽悠,用真实数据说话。

如果你正在为业务挑选中转站、想横向对比多家平台的真实表现,可以参考 openairouter.net 的平台对比与排行榜,作为压测前的初筛参考。

相关阅读

找到最适合你的 AI API 中转站

收录 125+ 服务商,按价格、模型、标签一键筛选

查看所有中转站 →