生成环境同事反映每到早上7-8点,高峰期服务卡死,日志疯狂打印,接口不能用,持续半个小时到一个小时,
那就怼呗,早上6点多赶到公司在服务卡顿时排查:
1 首先top看cpu飙高80以上甚至100%,其中mysql进程高达1000%,java300%。好吧,不用说肯定mysql或者sql有问题,看mysql配置好像没啥问题。
那就是sql了,把mysql-slow.log慢sql日志拿出来,一条一条sql全部优化一遍,加索引,改sql各种操作搞了一上午加半个下午。
此时服务器过来7-8点的卡顿时间段了,查询业务性能确实提高,mysql cpu也降下来了稳定在50%左右,整个服务器cpu也下来了,5-20%的波动。当时就想这下应该是没问题了。
mysql优化比完,但是过了高峰期看不出来7-8点效果,只能等第二天了。
2 第二天早上一看,我去,又卡死,怎么办,再看cpu,也没飙高到之前,最高70%,设置的cpu过80%告警都没触发,怎么回事?
继续查,
接口访问量过大?调出系统日志,nginx日志access.log统计一波,并发量不大啊
网络问题?ping服务器发现没有丢包,nethogs测网也正常,好,排除
io读写问题?iostat -x 1 io有波动,但也没发现io等待时间过长的异常现象,好吧,也不是这个问题,不过由于我们的内存是足够的100g呢,还是优化了一下/sys/block/sda/queue/nr_requests,128改到512,
内存问题?free -h 发现buff/cache超大,used才机器的一半内存,剩下的这么都在buff/cache 于是 echo 1 > /proc/sys/vm/drop_caches。
嗯,这样应该没啥问题了
3 第三天发现又是难受的一天,还是卡得一批,这个要干上了啊
只能上终极武器jvm了,
1 使用top命令定位异常进程。可以看见12836的CPU和内存占用率都非常高
2. 使用top -H -p 2370进程号查看异常线程
3 获取线程id的16进制,printf "%x\n" 50342线程id
4 jstack 进程号 | grep 线程id16进制
jstack 11800 | grep `printf "%x\n" 12608` -A 10
jstack -l 11800
发现DubboServerHandler WAITING这个不是dubbo嘛,哦,一看原来是dubbo线程池500不够用,于是改成1000,dispatcher 还是默认的?改message
<dubbo:protocol name="dubbo" port="31880" dispatcher="message" threads="1000" />
还有gc? 原来启动脚本啥参数也没给,于是改成:
java -XX:+UseG1GC -Xmx32g -XX:MaxGCPauseMillis=200 -jar xxx
4 第四天一看 我靠,系统空闲是性能提升了,但是还有卡顿,于是想到了定时任务,查看项目所有定时任务,统计执行时间,对调接口响应时间长的定时任务做异步处理,调用频繁的查询接口使用缓存直接返回结果,大功告成!
总结:性能问题
1 cpu、内存、io进程排查,使用 top、iotop、nethogs、iostat -x 1等命令
2 慢sql优化,加索引,sql逻辑
3 接口响应慢的,缓存
4 执行时间长的定时任务,异步
5 对3、4中的业务逻辑排查是否存在循环查库操作等
5 中间件(dubbo、redis、mysql等)性能参数优化,线程池大小等
6 jvm优化:jstack,gc等
感谢阅读!