BlueXIII's Blog

热爱技术,持续学习

0%

物联网平台压测报告

压测目的

本次压测意在寻找性能拐点,评估最大处理能力,并不断摸索操作系统与应用的调优参数

压测方案

压测场景

模拟单灯控制器,建立TCP链接,发送登录报文。登录成功后,不间断的发送属性上报消息。

创建虚拟设备

编写简易的JUnit脚本,以便于批量创建删除设备

录入10万个设备,设备ID为: 000000000001~000000100000

编写设备模拟器

由于单灯控制器通过TCP私有协议与平台进行通信,且上报消息的内容不固定,所以很难使用JMeter等常规压测工具进行测试。

需要自行编写单灯控制器模拟器,做为压测客户端,使用VertX异步框架开发以提高并发性能。

服务器指标监控

部署Prometheus+Grafana,进行图形化监控,方便查询历史指标并找出瓶颈点

消息样例

  • 登录(42字节): 68230068000000002000002226130007500100020802034C4F43373930302D4331454C36313000A35116
  • 属性上报(58字节): 68330068010000001300000e0000002001011003112700010fce590000003b400000dd242a426400000000000000000000000014000000f01216

压测环境搭建

服务端配置

  • 1台普通台式机,配置为i7-7700 4核8线程/16G/256G/千兆LAN
  • 最小化部署,应用及中间件混合部署在同一台服务器

服务端组件清单

类别 名称 版本号
应用 bifrost-ui 1.0.0
应用 bifrost-app 1.0.0
中间件 redis 5.0.4
中间件 elasticsearch 6.8.11
中间件 kibana 6.8.11
中间件 postgres 11-alpine
JDK openjdk 1.8.0_382
监控 grafana 10.3.3
监控 prometheus 2.50.1
监控 nodeExporter 1.7.0

服务端地址信息

类别 地址 帐密
单灯TCP端口 10.90.22.200:1886
UI http://10.90.22.200:9000 admin/1qaz@WSX
Redis 10.90.22.200:6379 仅密码:bifrost!23
ES6 http://10.90.22.200:9200
Kibana http://10.90.22.200:5601
Postgres postgres://10.90.22.200:5432/bifrost postgres/bifrost!23
Grafana http://10.90.22.200:3000 admin/1qaz@WSX

压测客户端

  • 4台Ubuntu虚拟机,配置为:8C/16G/500G/千兆LAN(实际只用到2台)
  • Ulimit与内核参数的优化,与服务端保持一致
  • 部署自行编写的单灯控制器模拟器

启动参数(以1万并发,120秒为例):

1
java -jar catonelight-simulator-1.0.0-SNAPSHOT.jar --host=10.90.22.200 --port=1886 --start=1 --parallels=10000 --duration=120

压测详细记录

请参考11~12轮的结果即可,点击跳转至语雀在线表格:
https://tc-aiot.yuque.com/org-wiki-tc-aiot-ms6e4o/tabv3n/zug68i5yymut8vlg#CyG5

结果分析

  • 8核16G的单机配置下,极限吞吐量为95502 TPS,极限并发数约为80000个设备
  • 随着并发数的不断提升,TPS保待不变,响应时间成比例的增加。系统并未出现明显拐点。
  • 内存占用量平稳,6-8G,基本无变化,上下文切换保持在60K左右
  • 系统负载稳定保持在15左右(处理器为8核心),以上都是Reactor带来的收益
  • 日志IO对性能的影响比预想中大很多,需要最先调优,同时需要兼顾实用性,不能完全关闭。优化后的性能提升约15倍。
  • Docker方式和原生JDK方式,在参数相同的情况下,TPS会有较大差异,各有胜负,原因不明
  • 关闭TCP粘拆包处理,可获得约30%的性能提升
  • 关闭Reactor的DebugAgent后,可获得约40%的性能提升

参数调优

操作系统Ulimit

1
2
3
4
5
6
7
# Ulimit设置
cat <<EOF >> /etc/security/limits.conf
root soft nofile 1048576
root hard nofile 1048576
root soft stack 1048576
EOF
sysctl --system

操作系统内核参数(修改前)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
cat <<EOF >> /etc/sysctl.conf
net.core.rmem_max=16777216
net.core.wmem_max=16777216
net.core.netdev_max_backlog = 30000
net.core.somaxconn = 262144
net.ipv4.neigh.default.gc_stale_time=120
net.ipv4.conf.all.rp_filter=0
net.ipv4.conf.default.rp_filter=0
net.ipv4.conf.default.arp_announce = 2
net.ipv4.conf.lo.arp_announce=2
net.ipv4.conf.all.arp_announce=2
net.ipv4.ip_local_port_range = 1024 65535
net.ipv4.tcp_rmem=4096 87380 16777216
net.ipv4.tcp_wmem=4096 65535 16777216
net.ipv4.tcp_fin_timeout = 10
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_timestamps = 0
net.ipv4.tcp_window_scaling = 0
net.ipv4.tcp_sack = 0
net.ipv4.tcp_syncookies = 0
net.ipv4.tcp_max_orphans = 262144
net.ipv4.tcp_max_syn_backlog = 262144
net.ipv4.tcp_max_tw_buckets = 5000
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_syn_retries = 2
net.ipv4.tcp_no_metrics_save=1
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
net.ipv6.conf.lo.disable_ipv6 = 1
vm.swappiness = 0
kernel.sysrq=1
fs.file-max=1000000
#fs.file-nr=1000000
vm.overcommit_memory = 1
EOF
sysctl -p

操作系统内核参数(修改后)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
net.ipv4.tcp_max_tw_buckets=50000
net.ipv4.tcp_max_syn_backlog=262144
net.core.somaxconn=262144
net.ipv4.tcp_tw_reuse=1
net.ipv4.tcp_tw_recycle=1
net.ipv4.tcp_rmem=4096 87380 16777216
net.ipv4.tcp_wmem=4096 65535 16777216
net.ipv4.tcp_mem=786432 2097152 3145728
net.ipv4.ip_local_port_range=1024 65535
vm.swappiness=0
kernel.sysrq=1
#fs.file-nr=100096 0 1531742
fs.file-max=1048576
vm.overcommit_memory=1

TCP粘拆包脚本

1
2
3
4
5
6
7
8
parser.fixed(4)
.handler(function (buffer, parser) {
var len = buffer.getShortLE(1);
parser.fixed(len + 3).result(buffer);
})
.handler(function (buffer, parser) {
parser.result(buffer).complete();
});

默认情况下,可以不启用粘拆包,以获得30%以上的性能提升

日志优化

  • 开启Console日志+文件日志+设备ES日志
  • 并逐行调整日志级别,大部分置为INFO级,兼顾实用
  • 关闭Logback的ES日志(怀疑这部分程序有问题会产生阻塞,关闭后TPS提升20倍)

应用优化

  • 关闭Reactor调试模式 spring.reactor.debug-agent.enabled=false,可获得约40%的性能提升
  • 关闭平台链路跟踪 trace.enabled=false
  • 后续如有必要时,将单个TCP连接的接收队列长度由默认256调高到65535,以应对单一设备连续上报的场景。需要修改VertX代码。

JVM优化

1
2
3
4
5
6
java -Duser.language=zh -XX:+UseG1GC -server \
-XX:+UnlockExperimentalVMOptions \
-XX:+UseCGroupMemoryLimitForHeap \
-XX:-OmitStackTraceInFastThrow \
-Djava.security.egd=file:/dev/./urandom \
-jar bifrost-standalone.jar