java 服务cpu100%问题排查

双11临近,领导让我们排查负责项目往年双11流量情况,预估服务是否有扩容需求
打开grafana看到有一个服务cpu使用总是100%+,代码拉取到本地开始翻代码
主要排查并行计算:多线程、parallelStream、completeableFeature、ForkJoinPool
一顿搜索发现如下代码:

   Map coordinateMap = Maps.newHashMap();
        bizOptionRoomFloorInfoDOList.parallelStream().forEach(f -> {
            if (StringUtils.isNotBlank(f.getFloorCoordinate())) {
                coordinateMap.put(StringUtils.join(f.getBuildingNo(), f.getFloorNo()), f.getFloorCoordinate());
            }
            if (StringUtils.isNotBlank(f.getRoomCoordinate())) {
                coordinateMap.put(f.getRoomNo(), f.getRoomCoordinate());
            }
        });
        List pmsHallInfoResponseDTOList  = pms2020BaseResponse.getTarget();
        pmsHallInfoResponseDTOList.parallelStream().forEach(h -> {
            h.getFloorResponseDTOList().parallelStream().forEach(f -> {
                if ((coordinateMap.containsKey(StringUtils.join(h.getHallId(),f.getFloorNo())))){
                    f.setCoordinate(coordinateMap.get(StringUtils.join(h.getHallId(), f.getFloorNo())));
                }
                f.getRoomResponseDTOList().parallelStream().forEach(r -> {
                   if (coordinateMap.containsKey(r.getRoomNo())){
                       r.setCoordinate(coordinateMap.get(r.getRoomNo()));
                   }
                });
            });
        });

写这段代码的哥们已经离职了,所以放心的吐槽了一波;(本身多线程场景使用HashMap也存在线程安全问题)
lambda parallelStream只是用来做了数据封装的操作,其实效率是不如for循环的(4核8G);jdk本身对for循环做了优化;数据拼装类的代码jdk本身也会jit优化
由于parallelStream底层是基于ForkJoinPool,而ForkJoinPool默认的线程数为cpu核数(4线程);
解决思路
1:将ForkJoinPool/多线程 线程数调低(这种方式不建议在数据拼装等场)
2:cpu密集性场景线程池数量尽量小(需要结合计算吞吐量进行调优)
3:修改为for循环
所以优化后上线cpu稳定在30左右;并且接口平均耗时也比原来低一些

你可能感兴趣的:(java 服务cpu100%问题排查)