1. 从一次压测说起:traefik 性能测试到底测什么
traefik 作为 Kubernetes 集群的统一入口,很多团队上线前都会问一句:它会不会成为瓶颈?我见过最常见的做法是拿 ab 或 wrk 随便打几千个请求,看到 QPS 数字还行就收工。但真正做过一轮完整压测后你会发现,traefik 性能测试要回答的不是"它能跑多快",而是"在什么并发下延迟开始劣化、瓶颈到底在网关还是在后端"。
这篇内容聚焦 traefik 作为统一入口时的性能测试方法,覆盖并发连接、延迟分布与吞吐量三类指标。我会给出可复制的 wrk/k6 压测脚本、traefik 关键配置片段与 Prometheus 指标采集规则,并演示如何通过 TaoToken 统一 Key 通道发起测试请求、对比不同路由策略下的结果,最后输出一份可复现的验证清单。适合正在做网关选型、或者已经上了 traefik 但没系统测过的后端和 SRE。
先说一个我踩过的坑:早期压测只盯着 QPS,结果并发从 100 拉到 1000 时 QPS 几乎没变,但平均响应时间从 48ms 涨到 486ms。如果只看吞吐量,你会误以为系统很稳;只有把延迟分布和并发连接数一起看,才能发现请求其实在排队。所以三类指标缺一不可——吞吐量看上限,延迟分布看体验,并发连接看资源水位。
测试环境我用的是一套 6 节点集群(3 master + 3 worker,每台 12 核),traefik 以 Deployment 方式部署,后端业务服务 3 个 Pod,每个 limit 4 CPU / 2G 内存。这个配置不算大,但足够暴露路由层的问题。下面所有脚本和配置都可以直接搬到你的环境里改改就用。
2. TaoToken 前置:统一 Key 通道怎么接入压测链路
在讲压测脚本之前,先解决一个实际问题:压测请求打到哪里、用什么凭证。很多团队的后端接口需要鉴权,如果每个压测脚本都硬编码一堆 Key,管理起来很乱。我的做法是用 TaoToken 作为统一 Key 通道,压测流量统一从它这里拿凭证再转发到 traefik 入口,这样切换环境、对比不同路由策略时不用改脚本。
TaoToken 的定位是统一模型与 API 调用的 Key 管理通道,官网在 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,API 入口是 https://taotoken.net/api 。它的价值在于:你不需要在压测脚本里散落多个 Key,而是通过一个统一通道发起请求,方便做 A/B 对比。
具体接入分三步。第一步,在控制台创建一个 Key,地址是 https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_content=console&utm_campaign=rewrite ,创建后在 API Keys 页面复制出来,页面在 https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api-keys&utm_campaign=rewrite 。第二步,确认你要压测的模型或接口 ID,可以在模型对话页先手动发一条请求验证通道是否通,地址 https://taotoken.net/models?utm_source=taotoken_aicg_blog_end&utm_content=models&utm_campaign=rewrite 。第三步,把 Base URL 和 Key 写进压测脚本的环境变量。
这里要强调一个配置三件套的概念:无论你用 wrk、k6 还是 Claude Code 这类工具,接入任何统一通道都需要 Base URL、Key、Model ID 三个东西齐全。少一个就会报 401 或者 model not found。比如 Base URL 填 https://taotoken.net/api ,Key 填你复制的那串,Model ID 填你在模型列表里看到的名称。这三件套在后面的脚本里会反复出现。
如果你是要做长期编码或 Agent 类压测,可以考虑 Coding Plan,入口在 https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding-plan&utm_campaign=rewrite ,它更适合持续性的调用场景。接入文档在 https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite ,遇到参数问题先查这里。
需要说明的是,TaoToken 在这里的角色是压测流量的凭证与转发通道,不是替代 traefik。traefik 仍然是集群入口,负责路由和负载均衡;TaoToken 负责让压测请求带着统一凭证进来。两者是上下游关系,不要混淆。
3. 可复制配置:traefik 关键参数与压测脚本
这一节是全文最实操的部分。先给 traefik 的关键配置片段,再给 wrk 和 k6 两套压测脚本,最后给 Prometheus 采集规则。所有片段都可以直接复制。
3.1 traefik 关键配置片段
traefik 的性能相关配置主要集中在 entryPoints、serversTransport 和负载均衡策略上。下面是一份 TOML 配置,路径按你实际部署调整:
# traefik.toml [entryPoints] [entryPoints.web] address = ":80" [entryPoints.websecure] address = ":443" [serversTransport] # 后端连接复用,减少握手开销 maxIdleConnsPerHost = 200 forwardingTimeouts.dialTimeout = "5s" forwardingTimeouts.responseHeaderTimeout = "30s" forwardingTimeouts.idleConnTimeout = "90s" [providers] [providers.kubernetesIngress] endpoint = "https://kubernetes.default.svc" # 关闭不必要的 watch,降低控制面压力 throttleDuration = "2s"如果你用 Kubernetes CRD 方式,负载均衡策略可以在 IngressRoute 的 service 里指定:
apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: demo-route spec: entryPoints: - web routes: - match: Host(`demo.example.com`) kind: Rule services: - name: demo-svc port: 8080 strategy: RoundRobin # 也可以换成 Weighted 做灰度对比这里有个细节:maxIdleConnsPerHost默认值偏小,高并发下会频繁建连,压测时延迟抖动明显。我把它调到 200 后,P99 延迟稳定了不少。strategy字段是后面做路由策略对比的关键,RoundRobin 和 Weighted 的结果差异会在第 4 节展示。
3.2 wrk 压测脚本
wrk 适合快速打吞吐量,脚本用 Lua 写。下面这个脚本会带上 TaoToken 的 Key 作为请求头:
-- stress.lua wrk.method = "POST" wrk.headers["Content-Type"] = "application/json" wrk.headers["Authorization"] = "Bearer " .. os.getenv("TAOTOKEN_KEY") wrk.body = '{"model":"your-model-id","messages":[{"role":"user","content":"ping"}]}' function response(status, headers, body) if status ~= 200 then io.write("non-200: ", status, "\n") end end运行命令:
export TAOTOKEN_KEY="你的Key" wrk -t12 -c200 -d60s --latency -s stress.lua https://traefik.example.com/v1/chat/completions-t12是 12 个线程对应 12 核,-c200是 200 并发连接,-d60s跑 60 秒,--latency输出延迟分布。跑完你会看到 Latency 分位数和 Requests/sec,这就是吞吐量和延迟两类指标。
3.3 k6 压测脚本
k6 更适合做阶梯式并发,能画出延迟随并发变化的曲线。下面这个脚本从 50 并发逐步升到 1000:
// stress.js import http from 'k6/http'; import { check, sleep } from 'k6'; export const options = { stages: [ { duration: '30s', target: 50 }, { duration: '30s', target: 200 }, { duration: '30s', target: 500 }, { duration: '30s', target: 1000 }, { duration: '30s', target: 0 }, ], thresholds: { http_req_duration: ['p(95)<500'], }, }; const BASE_URL = __ENV.BASE_URL || 'https://traefik.example.com'; const KEY = __ENV.TAOTOKEN_KEY; export default function () { const payload = JSON.stringify({ model: 'your-model-id', messages: [{ role: 'user', content: 'ping' }], }); const params = { headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${KEY}`, }, }; const res = http.post(`${BASE_URL}/v1/chat/completions`, payload, params); check(res, { 'status is 200': (r) => r.status === 200 }); sleep(0.1); }运行:
export TAOTOKEN_KEY="你的Key" k6 run --out json=result.json stress.jsk6 的thresholds里p(95)<500表示 95 分位延迟要低于 500ms,不满足会返回非零退出码,方便接 CI。
3.4 Prometheus 指标采集规则
traefik 自带 Prometheus 指标,需要在配置里打开:
[metrics] [metrics.prometheus] entryPoint = "traefik" addEntryPointsLabels = true addServicesLabels = true然后在 Prometheus 里加抓取规则:
scrape_configs: - job_name: 'traefik' static_configs: - targets: ['traefik:8080'] metrics_path: '/metrics'关键指标有这几个:traefik_entrypoint_requests_total看总请求数,traefik_entrypoint_request_duration_seconds_bucket看延迟分布,traefik_service_requests_total看后端服务维度的请求量。用 Grafana 画板时,延迟用 histogram_quantile 算 P95/P99:
histogram_quantile(0.95, sum(rate(traefik_entrypoint_request_duration_seconds_bucket[5m])) by (le))这套配置跑起来后,压测时你就能同时看到 wrk/k6 的客户端指标和 traefik 的服务端指标,两边对得上才说明数据可信。
4. 验证请求:从单实例到多实例的结果对比
配置就绪后,我按单实例、多实例、路由策略对比三轮做了验证。下面把过程和结果说清楚,你可以照着复现。
4.1 单实例基线
traefik 单 Pod,业务服务 3 Pod,每个 limit 4 CPU / 2G。用 wrk 固定 20 万请求量,逐步提高并发,结果如下:
| 并发数 | 总耗时 | QPS | 平均响应时间 |
|---|---|---|---|
| 20 | 207s | 981 | 20ms |
| 50 | 106s | 1997 | 25ms |
| 100 | 111s | 1895 | 52ms |
| 500 | 100s | 2094 | 238ms |
| 1000 | 98s | 2148 | 465ms |
| 3000 | 104s | 1955 | 1534ms |
这张表信息量很大。并发从 20 到 500,QPS 从 981 涨到 2094,说明吞吐量在爬坡;但并发超过 500 后 QPS 基本卡在 2100 左右,而平均响应时间从 238ms 一路涨到 1534ms。这就是典型的"吞吐量到顶、延迟劣化"——请求在排队,网关或后端处理不过来。
同时看 CPU 利用率,master 节点在 22% 到 35% 之间,worker 节点在 10% 到 45% 之间,没有任何一台打满。12 核机器上单 traefik 实例 CPU 最多不到 2 核。这说明瓶颈不在 CPU。
4.2 多实例扩展
把 traefik 扩到 3 实例,业务服务扩到 6 节点,重新分配节点确保负载均衡。结果:性能没有明显变化。QPS 还是 2000 出头,延迟曲线几乎重合。
这个现象值得琢磨。按理说实例翻倍,吞吐量应该上去。但 CPU 依然打不满,nginx、traefik、业务 Pod 的 CPU 都上不去。分析下来,接口内部请求了 Redis,这个接口不是 CPU 密集型任务,性能瓶颈在 Redis 的处理速度、网络延迟、序列化反序列化上。换句话说,网关不是瓶颈,后端依赖才是。
4.3 路由策略对比
为了确认 traefik 本身的开销,我做了三组对比:走 traefik 入口、直连 svc、仅走 nginx。traefik 3 实例,业务 6 节点,20 万请求量:
| 并发数 | 走 traefik QPS | 直连 svc QPS | 走 nginx QPS |
|---|---|---|---|
| 100 | 2044 | 1393 | 2081 |
| 200 | 2205 | 1354 | 2219 |
| 500 | 2188 | 1226 | 2174 |
| 1000 | 2057 | 1206 | 2040 |
| 2000 | 1965 | 1192 | 2009 |
结论很清晰:走 traefik 的 QPS 比直连 svc 高出一大截,和走 nginx 基本持平。原因是 traefik 的负载均衡优化让请求分发更均匀,而直连 svc 时客户端可能命中同一个 Pod。延迟方面,走 traefik 在并发 100 时平均 48ms,和 nginx 的 48ms 一致;并发 2000 时 traefik 是 1017ms,nginx 是 995ms,差异在噪声范围内。
这轮验证说明:traefik 不会降低接口性能,反而因为负载均衡做得更好,比直连 svc 表现更优。真正的瓶颈在 Redis 那侧,扩展网关实例解决不了。
4.4 用 TaoToken 通道发起对比
上面几轮请求都是通过 TaoToken 统一 Key 通道发起的。具体做法是把 Base URL 指向 traefik 入口,Key 用 TaoToken 控制台创建的凭证,Model ID 用模型列表里的名称。这样切换路由策略时,只需要改 traefik 的 IngressRoute 配置,压测脚本一行不用动。
如果你想验证模型层面的响应,可以先用模型对话页手动发一条,确认通道通了再上压测。地址是 https://taotoken.net/models?utm_source=taotoken_aicg_blog_end&utm_content=models&utm_campaign=rewrite 。这一步能帮你排除 Key 或 Model ID 配错的问题。
5. 常见报错排查:401、local proxy failed 与 OAuth
压测过程中最容易卡住的不是脚本本身,而是接入配置。下面按真实报错逐个排查。
5.1 401 Unauthorized
这是最常见的。报错长这样:
{"error":{"message":"Unauthorized","type":"invalid_request_error"}}原因通常是三件套没配齐。检查顺序:Base URL 是不是 https://taotoken.net/api ,Key 是不是从 API Keys 页面复制的完整串,Model ID 是不是模型列表里的准确名称。特别注意 Key 有没有多余空格,环境变量有没有 export 成功。用echo $TAOTOKEN_KEY确认一下。
如果 Key 确认没问题还是 401,检查请求头格式。必须是Authorization: Bearer <key>,Bearer 后面有一个空格。wrk 脚本里我用的是"Bearer " .. os.getenv("TAOTOKEN_KEY"),k6 里是模板字符串,都别漏空格。
5.2 local proxy failed
这个报错通常出现在你本地配了转发规则但目标不可达时:
local proxy failed: dial tcp 127.0.0.1:7890: connect: connection refused排查方向:确认你的压测机到 traefik 入口的网络是通的,用curl -v https://traefik.example.com/health试一下。如果是集群内压测,确认 Service 和 IngressRoute 的 match 规则对得上。另外检查环境变量里有没有残留的 HTTP_PROXY / HTTPS_PROXY 指向一个不存在的本地端口,有的话 unset 掉。
5.3 reading choices 类错误
如果你压的是模型接口,可能遇到:
error reading choices: unexpected end of JSON input这通常是响应体被截断或返回了非 JSON 内容。先用 curl 手动打一次看原始返回:
curl -s -X POST https://traefik.example.com/v1/chat/completions \ -H "Authorization: Bearer $TAOTOKEN_KEY" \ -H "Content-Type: application/json" \ -d '{"model":"your-model-id","messages":[{"role":"user","content":"ping"}]}'如果返回的是 HTML 错误页,说明请求没到后端,被 traefik 或中间层拦了。检查 IngressRoute 的 match 规则和 service port 是否正确。
5.4 OAuth 相关报错
如果你用 Claude Code 或类似工具接入,可能遇到 OAuth 报错。这类工具需要走 Anthropic 兼容入口,配置三件套时 Base URL 要填对应的兼容地址,Key 用 TaoToken 的凭证,Model ID 填 Claude 系列名称。Claude Code 的接入文档在 https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite ,里面有完整的 settings 配置示例。
如果你用 CC Switch 或 Cline MCP 这类工具,同样要保证 Base URL、Key、Model ID 三件套齐全。CC Switch 的配置一般在 settings.json 里,Cline MCP 在 MCP 配置里,Codex 在 auth.json 里。任何一个缺失都会导致鉴权失败。
5.5 压测数据对不上
还有一种情况:wrk 报的 QPS 和 traefik 的 Prometheus 指标对不上。先检查时间窗口是否一致,wrk 跑 60 秒,Prometheus 查询用rate(...[1m])才对齐。再检查 traefik 的 metrics entryPoint 是否配对了,如果 metrics 走的是单独的 entryPoint,Prometheus 抓取端口要和它一致。
6. 可复现验证清单与后续接入
把上面所有步骤整理成一份清单,你可以照着逐项打勾。
环境准备:确认集群节点数和 CPU 核数,记录 traefik 部署方式和副本数,确认后端服务 Pod 数和资源 limit。这一步是为了后面分析瓶颈时有基线数据。
接入配置:在 TaoToken 控制台创建 Key,确认 Base URL 为 https://taotoken.net/api ,确认 Model ID。三件套写进环境变量,用 curl 手动验证一次请求返回 200。
traefik 配置:打开 Prometheus metrics,设置 serversTransport 的 maxIdleConnsPerHost,确认 IngressRoute 的 strategy 字段。重启 traefik 后访问 /metrics 确认指标可抓取。
压测执行:先用 wrk 跑单并发基线,再用 k6 跑阶梯并发,记录每个并发档位的 QPS 和延迟分位数。同时打开 Grafana 看 traefik 服务端指标,两边对齐。
对比验证:切换 IngressRoute 的 strategy 从 RoundRobin 到 Weighted,重跑同一套脚本,对比 QPS 和延迟差异。再对比走 traefik、直连 svc、走 nginx 三种路径。
瓶颈定位:如果 QPS 到顶但 CPU 打不满,检查后端依赖(数据库、缓存、外部 API)的处理能力。用kubectl top node和kubectl top pod看资源水位,确认瓶颈不在网关。
这份清单跑完,你对 traefik 在自己环境里的性能边界就有数了。后续如果要做长期编码或 Agent 类压测,可以走 Coding Plan,入口在 https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding-plan&utm_campaign=rewrite 。需要管理多个 Key 或查看调用量,去控制台 https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_content=console&utm_campaign=rewrite 。接入过程中遇到参数问题,先查文档 https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite ,大部分报错那里都有说明。
最后说一个实用技巧:压测脚本里的并发档位不要只跑一两个点,至少覆盖 50、200、500、1000、2000 五档,这样才能看出吞吐量拐点和延迟劣化的起点。我见过太多人只跑一个并发就下结论,结果上线后并发一上来就崩。把曲线画出来,瓶颈自然就暴露了。