前言
这篇来讲解线上环境遇到问题,并如何解决,大概从内存,cpu,无响应、以及多线程和最优多线程性能问题来解决
- 内存
- cpu利用率高
- 无响应
- 多线程访问接口注意哪些事项
- 最优提高多线程性能
一、内存泄漏和内存溢出区别以及怎么优化
1.1、定义
- 内存泄漏:是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄漏似乎不会有大的影响,但内存泄漏堆积后的后果就是内存溢出。
- 内存溢出:申请内存前,系统已经不能再分配出你所需要的空间,保OOM错误。
1.2、内存泄漏可以分为4类
- 常发性内存泄漏:发生内存泄漏的代码,每次被执行的时候都会导致一块内存泄漏。
- 偶发性内存泄漏:发生内存泄漏的代码只有在某些特定环境或操作过程下才会发生。
- 一次性内存泄漏。发生内存泄漏的代码只会被执行一次,或者由于算法上的缺陷,导致总会有一块仅且一块内存发生泄漏。
- 隐式内存泄漏。程序在运行过程中不停的分配内存,但是直到结束的时候才释放内存。严格的说这里并没有发生内存泄漏,因为最终程序释放了所有申请的内存。
1.3、内存溢出可能情况
- 检查对数据库查询中,是否有一次获得全部数据的查询。
- 检查代码中是否有死循环或递归调用。
- 检查是否有大循环重复产生新对象实体。
- 检查List、MAP等集合对象是否有使用完后,未清除的问题。List、MAP等集合对象会始终存有对对象的引用,使得这些对象不能被GC回收。
1.4、内存溢出解决办法
- 修改JVM启动参数,直接增加内存。(-Xms,-Xmx参数一定不要忘记加。)
- 检查错误日志,查看“OutOfMemory”错误前是否有其 它异常或错误。
- 对代码进行走查和分析,找出可能发生内存溢出的位置。
- 使用内存查看工具动态查看内存使用情况
二、生产服务器CPU突然利用率高
遇到原因
- 程序计算比较密集:任务调度和业务逻辑拆分,任务调度底层死循环
- 程序死循环
- 程序逻请求堵塞
- IO读写太高
- 设置网关、过滤、保证接口幂等性问题
- 被攻击,高并发。安装服务器监听工具,设置提醒
linux排查
- 先找到Java的进程号
top -c 查看CPU使用率高的进程的PID
- 找到里面是哪个线程占用率最高
top -H -p <pid> 查看该进程所有线程信息,找到占用率最高的那个
- 得到线程号的16进制
printf "%x\n" <pid>
- 分析dump查找问题代码片
可以用 jstack <pid> | grep -A <tid> 来实时获取内存中该线程代码片,这里<tid>是第3步中得到的16进制的id
- 分析dump文件
- 启动jvisualvm,并查看目标java进程信息,然后选择Sampler -> CPU -> Thread CPU Time
三、应用无响应如何处理
服务器没有及时线程池处理请求:走服务熔断,降级返回友好提示,代码将低耗时的代码采用异步(MQ、多线程)执行
四、多线程访问接口注意哪些事项
- 当多线程访问一个接口,有可能遇到线程安全。此时应使用lock锁和sys锁
- 如果接口耗时久,可以将耗时代码改成异步处理(MQ,多线程)
- 接口幂等性问题:
- 如果接口是insert,根据全局ID做唯一约束
- 如果update情况,根据版本号解决防止ABA
- 安全相关防护,防止攻击
五、如何最优提高多线程性能问题
- 使用线程池复用机制,不建议单独创建线程,从而提高多线程效率
- 建议使用乐观锁CAS,自旋,不建议使用悲观锁(乐观锁:消耗cpu,不阻塞,悲观锁:有阻塞)
- 使用sys锁时,尽量降低锁的持有时间,使用偏向锁和轻量锁,否则变为重量级锁情况,效率低(偏向锁-->轻量锁-->短暂自旋-->重量级锁阻塞)
- 使用锁的采用分段锁,减少锁的粒度
- 最好使用多核服务器,避免频繁切换上下文