Tomcat BIO与NIO连接器性能测试:如何体现NIO优势?
如何设计测试凸显Tomcat NIO vs BIO的性能优势
一、高并发短请求场景(最能体现差异的核心场景)
准备工作
- 修改测试接口:移除随机sleep逻辑,直接返回固定JSON,模拟真实业务中常见的短平快接口(比如基础数据查询、健康检查)。
- Tomcat配置保持原有
Executor的maxThread=300、minSpareThreads=10,分别切换BIO(默认)和NIO连接器(在Connector标签中设置protocol="org.apache.coyote.http11.Http11NioProtocol")。
测试步骤
- 使用JMeter发起10000+并发请求(重点是并发数而非总请求数),持续压测2-3分钟:
- 线程组设置
线程数=1500(超过BIO线程池300的上限),Ramp-Up时间=0(瞬间拉起所有并发),循环模式选择“永远”。 - 监控核心指标:Tomcat线程数(通过JConsole查看)、请求响应时间(JMeter聚合报告)、错误率(连接超时/拒绝情况)、服务器CPU使用率。
- 线程组设置
预期差异
- BIO:线程数会迅速拉满至300,后续请求进入队列等待,响应时间大幅飙升,甚至出现大量连接失败;CPU因频繁的线程上下文切换,使用率居高但有效工作占比低。
- NIO:轮询线程数维持在极低水平(默认等于CPU核心数),工作线程数远低于300(短请求快速处理释放),总线程数比BIO少一大截;响应时间稳定,几乎无错误;CPU使用率更低,上下文切换开销显著减少。
二、大量长连接空闲场景
准备工作
- 保留短响应接口,Tomcat配置不变,JMeter启用HTTP长连接(在HTTP请求中勾选
Use KeepAlive,添加Connection: keep-alive请求头)。
测试步骤
- 构建5000+持久长连接,每个连接每隔10秒发送1次短请求,持续压测10分钟:
- 线程组设置
线程数=5000,Ramp-Up时间=60(1分钟内逐步拉起所有连接),循环模式选择“永远”,每个请求后添加10秒固定定时器。 - 监控核心指标:Tomcat线程数、内存占用(长连接的线程栈开销)、请求响应延迟。
- 线程组设置
预期差异
- BIO:每个长连接占用1个线程,300线程顶满后,剩余连接无法建立,出现大量连接失败;内存因线程栈占用过高快速飙升。
- NIO:所有5000个长连接由少量轮询线程管理,工作线程仅在处理请求时被唤醒,总线程数维持在几十到一百左右;内存占用远低于BIO,所有连接均可正常建立,请求响应延迟稳定。
三、I/O密集型业务场景
准备工作
- 修改测试接口为I/O密集型操作:比如读取100MB以上的本地文件返回,或调用外部慢API(模拟网络I/O阻塞),避免CPU密集型计算(如加密、大数据循环)。
- Tomcat配置不变,分别启用BIO和NIO连接器。
测试步骤
- 发起500并发请求,持续压测2分钟:
- 线程组设置
线程数=500,Ramp-Up时间=10,循环次数设为5次。 - 监控核心指标:Tomcat线程数、CPU使用率、吞吐量(每秒处理请求数)。
- 线程组设置
预期差异
- BIO:每个请求占用1个线程,300线程顶满后剩余请求排队;线程在I/O阻塞时完全闲置,吞吐量无法提升;CPU因频繁线程切换浪费资源。
- NIO:轮询线程负责监听I/O就绪事件,工作线程仅在I/O就绪时处理任务,线程数远低于300;I/O阻塞时线程可处理其他请求,吞吐量显著高于BIO;CPU使用率平稳,无频繁无效切换的开销。
关键注意事项
- 确认Tomcat连接器配置:BIO使用默认
protocol="HTTP/1.1",NIO必须指定protocol="org.apache.coyote.http11.Http11NioProtocol",避免配置错误。 - 区分线程类型:BIO线程前缀为
http-bio-xxx,NIO线程前缀为http-nio-xxx,可清晰观察轮询线程与工作线程的差异。 - 规避测试环境瓶颈:确保服务器CPU、内存、网络资源充足,避免硬件限制掩盖协议本身的性能差异。
内容的提问来源于stack exchange,提问作者vick_4444
相关产品推荐
相关产品推荐

