netty并发优化思路
有个基于netty的项目对并发要求较高,这里记录一下调优的过程
首先放弃常用的tomcat之类的容器方案,因为其性能不够,也不方便深入优化
Spring可以继续使用,仅使用IOC部分,不使用其web模块
业务逻辑本身比较简单,主要工作是写日志,第三方服务使用云厂商提供,响应速度极快,所以一次请求可以在1毫秒内完成
借助阿里云使用5000并发压测两分钟,刚开始请求响应在几十毫秒,后来拉到两秒,最终平均响应时间高达两秒,RTS 4000+
Linux上使用netty的epoll,其余继续使用nio,效果不明显
修改linux连接数量 vim /etc/sysctl.conf,修改
net.core.somaxconn和net.ipv4.tcp_max_syn_backlog,然后sysctl -p通过多种方式排查,可以认为是线程切换影响较大,可通过
netstat 1查看线程切换,正常在两三千左右,压测的时候直接五六万使用管道减少redis交互,效果不明显
将redis读写改为异步,效果明显,响应时间可在一秒内,测试10000并发,RTS也在10000+
进一步减小线程切换,将业务handler从原本的单独Group改为直接使用io线程池
将io线程数量限制为核心数+1,可通过top看到所有核心都在运转,只是使用率都不算高,整体使用率也才70%左右,所以核心数比单核性能更重要
通过arthas查看业务耗时情况,业务耗时一次不超过0.3毫秒,此时RTS依然是10000+,计算最大RTS (1000 / 0.3) * 8 = 26666,看似还有大量空间可优化,但是考虑到GC、上下文切换、其他程序竞争CPU,不好说还有多大优化空间
可通过https://gceasy.io/解析GC日志,jdk8可配置
-XX:-UseAdaptiveSizePolicy -XX:+PrintGCApplicationStoppedTime -XX:+PrintGCApplicationConcurrentTime -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+UseGCLogFileRotation -XX:+PrintHeapAtGC -XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=20M -Xloggc:/data/weblogs/ard-user-gc-%t.log -XX:+HeapDumpOnOutOfMemoryError输出GC日志