最近事情有点多,2019年的时间进度条已经过半,,更新不及时,以后还是得坚持两周一篇
背景
最近在做一件事情,通过tpcc客户端压测一下数据库,tpcc (前段时间阿里oceanbase夺得性能全球第一)公认的数据库压测工具,该客户端采用的是java,
内部嵌套jdbc。我们想实现对多个db分库同时压测,原先的tpcc已经不能满足我们的场景,我们做了多连接,tpcc客户端同时和多个db保持多条连接.我们发现
当想要实现单机100k连接,发现很难,所以开始想着开多个客户端最后汇总收集。但是,机器资源有富余,为什么不能?
认真的优化之路
- 首先,我们先开启100k的连接线程,将业务操作全部干掉,尽量减少资源浪费
- 其次,我们把已知的参数调整到最大,诸如jvm 参数,操作系统句柄数,还有tcp 参数
JVM 参数 xms40g xmx40g xss256k
- 在jdk1.8中xss
默认是1M,那我们为了尽量减少内存使用,我们使用比较低的设置256k,单线程256k*100k=25600M=25g,所以我们参数xmx要调整的高,当然这是我们初始设定 - 操作系统句柄数建议openfiles弄个很大的值,修改完后,ulimit -a查看一下
- 调整tcp参数的意义在于让单次连接效率更高
- 接着,当我们做好这些,准备跑的时候启动到3w并发时候挂了。。。
OOM 了,之前遇到的oom,三类
- heap space (最常见,增大内存使用就行)
- perm space(1.8后使用metaspace)
- gc overhead limit exceeded(查看gc使用)
这一下有点懵,stackoverflow 上搜了下
1 | ulimit -s 256 ulimit -i 120000 |
- 修改了配置后,过了一会后,发现又跪了,错误信息是关于memory overcommit的,
这一次查看了一下系统资源
1 | grep -i commit /proc/meminfo |
将db重启后修复
- 继续前行,起来之后又报了个错
这一次是socket
建立失败,我们看了下db日志,结果啥都没有,jdbc那里加上日志db的端口和ip也正常,这就很茫然了,我们继续看启动的线程数,当跑了多次之后发现,每次总在51072线程的时候,崩掉
我们想了下,每个机器能开的端口就是65536个,因为tcp报文16bit来表示端口,所以这个是改不了了,这下完蛋了。
仔细一想,不对啊,两个db,每个5w端口怎么着都够了啊,netstat -nao|grep
ESTABLISHED,发现确实最高到6w多就崩了,于是调整参数
1 | net.ipv4.ip_local_port_range = 40000 65535 |
当我们调整完后,好了,我们再回过头来看为什么到51072线程时候挂了呢,经分析是
(65536-40000)*2(两个db)= 51072
至此,100k并发,已经彻底满足,当然1000k并发需要增加db数也是可以玩起来的
那今天先聊到这,休息下眼睛