硬件配置:
压测客户端和服务器端在同一台pc上。Pc配置:
AMD A10-5800K APU with Radeon(tm) HD Graphics 3.80Ghz 四核
4G RAM
西数WDC WD10EZEX-60ZF5A0 ( 1 TB / 7200 转/分) 这个可以不写的
主要的测试目标分为:
1. 服务器端在一定时间内可接受客户端空闲连接的数量/峰值;
连接数 | 时间 |
1 | 180ms |
1000 | 1150ms |
2000 | 2207ms |
6000 | 9000ms |
每次建立tcp连接(包括web socket握手),平均需要180ms左右;
但是并不意味着 建立1000个连接需要180*1000ms,因为建立连接过程是异步的,详见压测客户端的代码。当建立较大量连接时(一万以内),所耗费的时间与连接数基本上是线性关系。
测试中,当测试6000连接数多于2次,在不重启jvm的情况下,测试程序客户端基本上就会报buffer空间不足的异常。
2. 服务器端同时保持空闲长连接的数量/峰值;
连接数 | 服务端java进程内存 | 服务端cpu利用率 |
0 | 358M | 0% |
6000 | 458M+ | 1% |
10000 | 458M+ | 1% |
服务器启动后,可以看到已使用内存为358M,客户端连接后为457M。它们之间的差值并不是保持所有连接 耗费的内存。因为建立连接过程中,在新生代中产生了很多垃圾内存。
标准的测试方法是:在开始连接之前,强制gc,这时看到是java进程真正占用的内存m1;在1w个连接建立之后,再次强制gc,用当前值m2减去上次gc后的内存值m1,才是保持连接实际占用的内存值,约为25M。
注意:频繁连接服务器建立1w个连接,即使全部断开,在客户端netstat –p依然可以看到这2w个端口在被占用着,未完全释放。这时就会出现异常 java.net.SocketException: No buffer space available (maximum connections reached?): connect
3. 分别在单个连接和多个连接的情况下,统计服务器端netty网络层的吞吐率。
单连接 客户端发送PingWebSocketFrame:
时间表示客户端从发送第一个ping消息 开始计时,在收到最后一个pong消息后结束计时。
ping次数 | 时间 |
1k | 160ms |
3k | 380ms |
5k | 550ms |
1w | 785ms |
10w | 2617ms |
100w | 24602ms |
多连接:
连接数 | 每个连接ping次数 | 时间 | 吞吐率 |
1k | 100 | 4280ms | 23364 |
1k | 500 | 10432ms | 47929 |
1k | 1k | 18082ms | 55303 |
1k | 2k | 36261ms | 55155 |
2k | 100 | 6900ms | 28985 |
2k | 500 | 19610ms | 50994 |
2k | 1000 | 33727ms | 59299 |
3k | 100 | 9752ms | 30762 |
3k | 500 | 31461ms | 47678 |
3k | 1000 | 56176ms 122491ms | 压测无法进行(丢包,卡) |
4. 测试网络流量
客户端向服务器端发送ClientRequest,payload为LoadTest对象,序列化为json字符串,大约800+个字符。可大致认为每条请求消息字符长度为800+。
连接数 | 每个连接请求次数 | 时间 | 平均每秒请求数 | IO性能(每秒字符数) |
1 | 1k | 566ms | 1766 |
|
1 | 5k | 1099ms | 4549 |
|
1 | 1w | 1157ms | 8643 |
|
1 | 10w | 5601ms | 17853 |
|
1k | 100 | 11094ms | 9013 |
|
2k | 100 | 25959ms | 7692 |
|
3k | 100 | 40062ms | 7500 |
|
|
|
|
|
|