使用jmeter压测Netty通讯服务
项目中使用
netty框架开发底层通讯服务器模块。设备与通讯服务器采用tcp长连接的通讯方式。建立链接过程使用ssl对连接通道进行加密。建立连接后定时向服务器发送心跳数据。
测试目标
- 单台
netty server维持长连接数量。 - 长连接数量增长下
tps指数。 - 长连接数量增长下
jvm的堆栈内存变化。
测试工具
- jmeter
- jvisualvm
数据准备
编写脚本准备100W终端信息。直接上代码。
|
|
- 使用
UUID生成100W mac地址 - 再使用生成的
mac地址分别生成sql脚本,添加到redis中 - 将
mac信息使用redis的哈希表数据结构进行存储redis.hset("dev_mac",String.valueOf(c), mac);dev_mac作为key循环mac集合的index作为hash_key,mac作为hash_value。这样处理方便多机分布式压测。 - 循环mac地址集合生成
sql脚本,为了进行批处理操作,每5000条mac数据作为一个insert into语句 - 测试脚本运行结束后,将生成的
sql脚本source到数据库中。
压力测试脚本
直接上代码
|
|
- 编写自定义压力测试脚本之前需要几部操作。
- 找到
jmeter安装目录/apache-jmeter-3.2/lib/ext将ext目录下的ApacheJMeter_core.jar和ApacheJMeter_java.jar引入进测试脚本的工程中。 - 将主类
extends AbstractJavaSamplerClient覆盖其中的两个方法runTest和setupTest。 - 在
setupTest方法中生成实例SampleResult对SampleResult进行设置 然后在runTest方法中进行添加。
- 找到
- 将编写好的脚本打包成
jar导入到jmeter目录/apache-jmeter-3.2/lib/ext中 , 再将压测脚本所需要的依赖包也导入到/apache-jmeter-3.2/lib/ext中。 - 打开
jmeter gui添加测试计划,编写测试计划,具体测试计划的线程组编辑下面再介绍。 - 使用命令进行压力测试
sh ./jmeter.sh -n -t /home/wanglp/communication-pressure-test/device-info/csjh.jmx-n表示no gui-t表示编写的测试计划。
测试计划的线程组编写
- 添加测试任务,再在测试计划下添加线程组,如图

- 线程数: 表示启动的线程总数。
- Ramp-up period : 表示多少秒后将设置的线程数全部启动。
- 循环次数: 表示该线程组配置循环执行几次。
Jvisualvm 的使用
jvisualvm 用来监控java程序的堆栈内存,cpu,线程,类加载数等信息的使用情况。jvisualvm程序包含在 jdk 家目录下 bin 目录下。为使得 jvisualvm 监控远程的 java 程序 需要为远程的java程序的启动脚本添加jmx参数。
|
|
其中 jmx 连接的端口。启动后远程程序后,再回到本机的 jvisualvm ,在远程一栏中添加远程主机,添加之后,再在远程主机下面添加 jmx 连接。
如图:
监控 jvisualvm 参数 如图:
测试报告
| 线程数 | 栈内存 | 堆内存 | 压测持续时间 | Server 状态 |
|---|---|---|---|---|
| 3000 | 128M | 256M | 1 小时 18 分 34 秒 | down |
测试发现的问题
- 从微服务获取证书时间长,将线程启动频率调整至 1 thread / 3s 以内时,微服务堆内存溢出。
- 随着压测时间的加长,
netty server的堆内存持续增加,直至堆内存溢出。