Java面试宝典 (五) | 线上生产环境常见面试题

Scroll Down

前言

这篇来讲解线上环境遇到问题,并如何解决,大概从内存,cpu,无响应、以及多线程和最优多线程性能问题来解决

  • 内存
  • cpu利用率高
  • 无响应
  • 多线程访问接口注意哪些事项
  • 最优提高多线程性能

一、内存泄漏和内存溢出区别以及怎么优化

1.1、定义

  • 内存泄漏:是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄漏似乎不会有大的影响,但内存泄漏堆积后的后果就是内存溢出。
  • 内存溢出:申请内存前,系统已经不能再分配出你所需要的空间,保OOM错误。

1.2、内存泄漏可以分为4类

  • 常发性内存泄漏:发生内存泄漏的代码,每次被执行的时候都会导致一块内存泄漏。
  • 偶发性内存泄漏:发生内存泄漏的代码只有在某些特定环境或操作过程下才会发生。
  • 一次性内存泄漏。发生内存泄漏的代码只会被执行一次,或者由于算法上的缺陷,导致总会有一块仅且一块内存发生泄漏。
  • 隐式内存泄漏。程序在运行过程中不停的分配内存,但是直到结束的时候才释放内存。严格的说这里并没有发生内存泄漏,因为最终程序释放了所有申请的内存。

1.3、内存溢出可能情况

  1. 检查对数据库查询中,是否有一次获得全部数据的查询。
  2. 检查代码中是否有死循环或递归调用。
  3. 检查是否有大循环重复产生新对象实体。
  4. 检查List、MAP等集合对象是否有使用完后,未清除的问题。List、MAP等集合对象会始终存有对对象的引用,使得这些对象不能被GC回收。

1.4、内存溢出解决办法

  • 修改JVM启动参数,直接增加内存。(-Xms,-Xmx参数一定不要忘记加。)
  • 检查错误日志,查看“OutOfMemory”错误前是否有其 它异常或错误。
  • 对代码进行走查和分析,找出可能发生内存溢出的位置。
  • 使用内存查看工具动态查看内存使用情况  

二、生产服务器CPU突然利用率高

遇到原因

  1. 程序计算比较密集:任务调度和业务逻辑拆分,任务调度底层死循环
  2. 程序死循环
  3. 程序逻请求堵塞
  4. IO读写太高
  5. 设置网关、过滤、保证接口幂等性问题
  6. 被攻击,高并发。安装服务器监听工具,设置提醒

linux排查

  1. 先找到Java的进程号
top -c 查看CPU使用率高的进程的PID
  1. 找到里面是哪个线程占用率最高
top -H -p <pid> 查看该进程所有线程信息,找到占用率最高的那个
  1. 得到线程号的16进制
printf "%x\n" <pid>
  1. 分析dump查找问题代码片
可以用 jstack <pid> | grep -A <tid> 来实时获取内存中该线程代码片,这里<tid>是第3步中得到的16进制的id
  1. 分析dump文件
  2. 启动jvisualvm,并查看目标java进程信息,然后选择Sampler -> CPU -> Thread CPU Time

三、应用无响应如何处理

服务器没有及时线程池处理请求:走服务熔断,降级返回友好提示,代码将低耗时的代码采用异步(MQ、多线程)执行

四、多线程访问接口注意哪些事项

  1. 当多线程访问一个接口,有可能遇到线程安全。此时应使用lock锁和sys锁
  2. 如果接口耗时久,可以将耗时代码改成异步处理(MQ,多线程)
  3. 接口幂等性问题:
  • 如果接口是insert,根据全局ID做唯一约束
  • 如果update情况,根据版本号解决防止ABA
  1. 安全相关防护,防止攻击

五、如何最优提高多线程性能问题

  1. 使用线程池复用机制,不建议单独创建线程,从而提高多线程效率
  2. 建议使用乐观锁CAS,自旋,不建议使用悲观锁(乐观锁:消耗cpu,不阻塞,悲观锁:有阻塞)
  3. 使用sys锁时,尽量降低锁的持有时间,使用偏向锁和轻量锁,否则变为重量级锁情况,效率低(偏向锁-->轻量锁-->短暂自旋-->重量级锁阻塞)
  4. 使用锁的采用分段锁,减少锁的粒度
  5. 最好使用多核服务器,避免频繁切换上下文