背景:公司的消息系统的保持长链接的服务(scala编写)。在IDC的机器(12C24G)上一直运行着,一直存在CPU过高,老员工写的2小时重启,重启缺失能解决问题。最近服务要上阿里云,使用4C8G的实例。不一会CPU使用率就到了600%,负载最高达到了16。所以解决CPU过高迫在眉睫。
定位问题:jvm上运行的服务导致CPU过高网上多数写的很清楚了。本项目是scala编写,所以适用,三板斧:
1、top查看CPU过高进程号(PID)
2、top -H -p PID 查看CPU使用率高的线程号(TID),接着转换十六进制 printf %x TID
3、jstack PID | grep 十六进制TID -A90
定位scala中map的findEntry方法导致的。定位代码此处的map是存放所有用户的链接信息。scala的Actor并发模型下访问此map。应该是map环链问题了。
解决:
源代码: var channelMap = Map[String, (ChannelHandlerContext, ActorRef)]() 注:查资料其value的类型是scala元组
优化使用java的支持并发的map,当时元组让我纠结了好一会,因为用的java类ConcurrentHashMap还想着把元组转成java对象才能传参。后来测试实则直接可以用,可以看出scala对java兼容。优化后代码:
var channeMap = ConcurrentHashMap[String, (ChannelHandlerContext, ActorRef)]()