zoukankan      html  css  js  c++  java
  • 线上六个性能问题案例分享

    1、动态条件查询未做非空判断引起CPU占用100%并引发事故
    代码示例:

    //message为解析外部存管行返回的消息内容并封装成的对象
    TppCgbankReq cgbankReq = new TppCgbankReq();
    cgbankReq.setBusiness(getTrxCode());
    cgbankReq.setOrderNo(message.getPreOrderNo());
    List<TppCgbankReq> list = tppCgbankReqService.getAll(cgbankReq);
    

    原因:
    一、在正常(业务成功)的情况下,message.getPreOrderNo()有值,在业务失败的情况下,message.getPreOrderNo()为null;
    二、tppCgbankReqService.getAll是一个动态条件查询方法,由于未对orderNo做判空处理,结果一次将整个表trxCode符合条件的记录(几十万)都查询出来了并load到堆中;
    三、由于堆空间长期紧张,频繁触发full gc引起CPU占用100%。

    解决方案:
    一、orderNo应该取message.getHeaderOrderNo(),此时不论业务成功或失败message.getHeaderOrderNo()都有值;
    二、防御性编码原则,由于orderNo是由外部系统报文解析而成,仍然存在为空的可能,加上非空判断。

    2、Rabbitmq由于消费者处理慢引起CPU及内存占用高企
    原因:
    Rabbitmq采用推模式,当消费者处理速度跟不上生产者速度时,由于未限制qos,消息在消费者端堆积,导致消费者堆空间占用上升,full gc也跟着上升,cpu及内存双紧张。

    解决方案:
    由于短时间内没办法将消费者速度提高到与生产者速度匹配,故设置qos,限制每次取得的消息数量为10,参考:channel.basicQos(10);。

    3、过多的线程导致cpu占用过高
    代码示例:

    //请求开始         
     //主业务操作          
    threadPool.execute(new Runnable() {                
        @Override               
         public void run() {                     
         //生成合同                
         }            
    });          
    //请求响应
    

    原因:
    一、多线程模型不合理,虽有使用线程池,一些非核心业务起了过多的线程处理,导致cpu占用过高;
    二、主业务处理完成后,使用了线程池异步生成合同,由于生成合同是IO密集型操作,高峰期时threadPool很快达到最大线程数;
    三、由于threadPool设置了过大值,起过多的线程导致CPU占用过高。

    解决方案:
    一、短期调整threadPool值为合适大小;
    二、长期将非核心异步任务使用MQ异步架构,使用异步消费线程处理;

    4、慢SQL引起数据库CPU上升,其他SQL被挂起,系统短时不可用。
    原因:
    报表慢sql引起阿里云RDS数据库CPU占用100%

    解决方案:
    1、及时KILL掉该任务;
    2、优化慢sql;
    3、读写分离,报表走读库。

    5、Netty写的TCP服务稳定跑了一个多月后,突然CPU占用100%
    原因:
    一、ByteBuf未手工释放引起堆外内存缓慢泄露,积累到一定程度后,由于空间不足,引起full gc并引起CPU占用100%;
    二、Netty某些旧版本确实也存在其他原因内存泄露的风险。

    解决方案:
    1、升级Netty到最新稳定版;
    2、主动释放手工建立的ByteBuf;
    3、日志加上堆外内存报告并打印。

    6、连接池设置过小,导致系统响应超时****原因:
    一、初时CPU及内存正常,系统响应超时,日志中大量获取数据库连接超时报错;
    二、由于核心业务操作接口是同步架构,资产端大量请求积压且频繁超时,造成资金端用户无法正常使用系统。

    解决方案:
    一、调整连接池,调大最大连接数等;
    二、【架构调整】资产端与资金端互相分离;
    三、【架构调整】将核心业务操作从同步操作修改为异步架构,引入MQ进行削峰处理。

    总结
    一般来说,引起CPU占用高的情况有:
    1、FULL GC;
    2、过多的Thread,线程频繁切换会耗费大量的CPU资源;
    3、不合理的循环,包括死循环,循环次数过多等;
    4、某些第三方lib等。

    一般来说,引起内存占用高的情况有:
    1、一次从数据库中查询过多数据,这个可以配合检查慢sql发起;
    2、资源使用后忘记释放或未考虑到抛出异常后的释放;
    3、大循环中创建过多的对象;
    4、使用全局的集合类缓存过多的数据等。

    线上排查的过程就是结合top、jstat、jmap、jstack命令验证以上猜想的过程如果线上无法很快定位问题,及时Dump文件到本地,再用MemoryAnalyzer、Jvisualvm等分析。

  • 相关阅读:
    Nginx负载均衡和LVS负载均衡的比较分析
    Nginx和Squid配合搭建的Web服务器前端系统
    (总结)Linux服务器上最简单的Nginx反向代理配置
    Nginx主要模块常用指令说明
    (总结)Nginx 502 Bad Gateway错误触发条件与解决方法
    (总结)Linux下查看Nginx Apache MySQL的并发连接数和连接状态
    (总结)统计Apache或Nginx访问日志里的独立IP访问数量的Shell
    IoC模式(依赖、依赖倒置、依赖注入、控制反转)
    使用OAuth打造webapi认证服务供自己的客户端使用
    RESTful API 设计指南
  • 原文地址:https://www.cnblogs.com/mzsg/p/11978017.html
Copyright © 2011-2022 走看看