TKeed 压测实战:WebBench 1000 并发下的吞吐量、CPU 占用与 8 worker 调优对比
【免费下载链接】TKeed🌎 High Performance HTTP WebServer项目地址: https://gitcode.com/gh_mirrors/tk/TKeed
TKeed是一款基于 Reactor 模型的高性能 HTTP WebServer,核心采用 epoll 非阻塞 I/O + 线程池架构。本文使用经典压测工具 WebBench,以1000 并发、60 秒为基准,实测 TKeed 的吞吐量(RPS)、CPU 占用与系统负载,完整对比 4 worker 与 8 worker 两种线程配置的调优结果,帮你在 5 分钟内掌握 HTTP 服务器压测方法与线程数调优经验。
一、压测环境:WebBench 压测快速上手
📌 本次压测环境如下(本地环境,保证结果可复现):
| 项目 | 配置 |
|---|---|
| CPU | 4 核 i5 处理器 |
| 操作系统 | Ubuntu |
| 压测工具 | WebBench 1.5(源码见test_unit/webbench/webbench.c) |
| 压测时长 | 每轮 60 秒 |
| 目标页面 | /index.html(约 515 字节) |
TKeed 默认监听 3000 端口,worker 线程数由配置文件 tkeed.conf 中的thread_num控制,服务构建与配置可在 makefile 与 main.c 中查看。
通过以下命令即可启动 WebBench 压测:
./webbench -t 60 -c 1000 http://127.0.0.1:3000/index.html-t 60:压测持续 60 秒-c 1000:模拟 1000 个并发客户端连接
WebBench 结束后会输出三项核心指标:Speed(每秒请求数与字节吞吐)、succeed 成功数、failed 失败数,它们是本文对比分析的全部依据。
二、1000 并发压测结果:4 worker 对比 8 worker 核心数据
同样的压测条件(1000 并发 × 60 秒),仅调整 worker 线程数,结果如下:
| 指标 | 4 worker | 8 worker |
|---|---|---|
| RPS(pages/min) | 671,102 | 641,383 |
| 带宽吞吐(bytes/sec) | 7,728,858 | 7,303,634 |
| 成功请求数 | 671,102 | 641,192 |
| 失败请求数 | 0 | 191 |
第一个结论可能有点反直觉:worker 线程从 4 加到 8,吞吐量不但没有提升,RPS 反而下降约 4.4%,还额外产生了 191 个失败请求。
下面是 8 worker 压测期间的系统负载截图,load average 仅约 1.03(4 核机器),每个 tkeed 线程 CPU 占用稳定在 5% 左右:
为什么线程越多,WebBench 压测结果反而越差?
这里有一条非常经典的调优经验:worker 线程数 = CPU 核心数。
- TKeed 的事件驱动循环本身是非阻塞的,epoll 负责把 I/O 事件拆分成独立任务分发给线程池;
- 1000 并发下 4 个线程已能消化全部 I/O 事件,再加 4 个线程不会带来真正的并行度提升;
- 多出来的线程只会引入线程上下文切换开销和线程池任务队列的互斥锁竞争,反而拖慢整体响应。
CPU 占用分析:满负荷下总 CPU 仅约 40%
这是本次压测最有说服力的一组数据:在 671,102 RPS 的满负荷下,TKeed 总 CPU 使用率仅约 40%(4 线程时单线程约 10%,8 线程时单线程约 5%)。
从上面的 top 截图可以印证:用户态时间(us)只有 19.8%,线程大部分时间处于"等待 epoll 事件就绪"的状态,而不是忙轮询。这正是 Reactor 事件驱动模型相比传统"一线程一连接"模型的本质优势——线程数与并发数解耦,CPU 占用可预测。
三、1KB 标准页面测试:响应体变大后吞吐量如何变化
将响应体换成 1KB 标准页面,同样 1000 并发 × 60 秒:
| 指标 | 数值 |
|---|---|
| RPS(pages/min) | 641,201 |
| 带宽吞吐(bytes/sec) | 12,831,604 |
| 成功 / 失败 | 641,083 / 118 |
页面体积从约 515B 增大到 1KB 后,RPS 略微下降(671K → 641K),但字节级吞吐量翻倍(7.7 MB/s → 12.8 MB/s)。这完全符合预期:RPS 与页面大小成反比,而带宽吞吐随页面体积同步放大。压测时用小页面测"连接处理能力"、用标准页面测"带宽能力",两者结合才是完整评估。
四、压测成绩背后的架构:Reactor 模型与线程池
TKeed 能在 4 个线程下跑出 67 万 RPS,靠的是这套架构(完整设计说明见项目内 架构分析.md 与 并发模型.md):
- 事件循环:epoll.c 负责 accept 连接、注册读事件与事件分发,内核监听就绪后才通知,全程不阻塞等待;
- 线程池:threadpool.c 用互斥锁 + 条件变量避免忙等,新任务入队后仅唤醒一个等待线程,规避惊群效应;
- 请求处理:http.c 的
do_request读取请求、状态机解析(http_parse.c)、返回响应文件,超时连接由 timer.c 的优先队列统一惰性清理。
下面是整个服务器模块与函数的调用关系全景图,可以清晰看到 main.c → epoll → threadpool → do_request 的完整调用链:
完整的压测原始数据与改进记录已归档在 测试及改进.md 中,欢迎对照复现。
五、调优结论:3 条可直接复用的经验
- 🎯 线程数对齐核心数:4 核机器上 4 worker 是最优解,8 worker 反而劣化;换机器时先设
thread_num = 核心数,再实验性微调; - 📊 看负载而不只看 RPS:本次 8 worker 压测 load average 仅 1.03,CPU 远未打满,瓶颈在锁竞争与调度开销,加线程没有意义;
- 🧪 小页面 + 标准页面双测:515B 页面反映连接处理能力,1KB 标准页面反映带宽能力,两者结合才能完整评估 WebBench 压测结果。
一句话总结:1000 并发下,TKeed 以 4 worker 达成 671,102 RPS、0 失败,总 CPU 占用仅约 40%;盲目把 worker 加到 8 得不偿失——"线程数 = 核心数"是最稳的 HTTP 服务器压测调优公式。
【免费下载链接】TKeed🌎 High Performance HTTP WebServer项目地址: https://gitcode.com/gh_mirrors/tk/TKeed
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考