一背景
最近在做视频点播的任务,需要制作一个程序来模拟2000个摄像头,对平台进行自动注册,心跳发送,目录推送,点播的功能,程序在另一名开发的基础的进行修改,使用netty作为客户端通信工具,开发好之后就给测试人员进行压测了,但是反应测试时候,只开启一千路模拟启动的时候, 客户端连接数量只能达到 500左右,程序假死,无法对netty的客户端进行任何操操作, 收到这个消息后我就开始问题排查,现将排查思路复现如下
二.场景复现
这个复现比较简单,直接在服务器上配置nettt连接工具的大小,启动netty程序,在服务端可以看到注册的大小,发现确实注册到500左右的时候,就不会添加了。 并且这个时候对客户端发送任何消息, 客户端也无法处理
三。排查思路
遇到这种问题,一般的思路就是
1.排查文件描述符限制数
2.查看cpu、内存使用率
3.查看线程使用情况
首先简单思考一下,这台服务器的cpu是32核,内存是126G,而这个netty只模拟1000路,服务器性能肯定是够的,接下来就开始进行排查
3.1 文件描述符限制数
在Linux系统中,文件描述符的限制控制着一个进程可以同时打开的文件数量。这些限制包括每个进程的软限制和硬限制,以及文件系统级别的限制
使用ulimit -u 查看系统级别的限制,发现是10240000,一千多万,没毛病
接着查看进程级别的限制
这里也是和系统限制保持一致,所以不是文件描述符限制的原因
3.2 查看内存
内存一共126G,目前才占用 5个G,内存不是问题
3.3 cpu查看
通过查看cpu,发现cpu使用率是3100%,基本32个核心都跑满了,于是问题就定位到时cpu的问题, cpu跑满,肯定是进程中开启了大量的线程, 线程太多,导致cpu跑满了,接下来就要分析线程
3.4 线程排查
使用arthas的dashbord,可以查看线程,内存的使用情况,比较直观
通过查看,主要线程占用有两类,一类是 pool开头的,一类是nioEventLoop开头的;
nioEventLoop大概率是处理netty-client数据的线程,为了区分,自己修改netty的处理线程
再次重启之后,发现线程名字确实改变了,印证了自己的想法,nioEventLoop确实是处理netty消息的线程
3.5 进一步查看有问题的线程
使用jstack {进程id}, 查看线程详情,结果如下
发现有问题线程,主要在
com.sailing.netty.SipProcessInboundHandler#printUDPCatalog
3.6 查看代码逻辑
通过查看代码,发现有bug,会导致这个线程死循环,从而导致cpu被全部占满, 将这个逻辑进修改后,在次部署
3.7 代码修改后重新部署
重新部署后,1000路客户端启动,cpu只用一个23%
同时服务端成功注册1000个客户端,进行操作,也都是好的,没毛病.