【记录】系统问题

背景

在日常开发中,自己或者同事也遇到过不少系统异常,是很宝贵的经验,以后会统一记录维护下来

JVM系列

动态代理产生过多的类,而没有回收

现象

外部请求几乎全是超时,jvm一直进行老年代回收,却无法回收,系统不可用

原因分析

原因分析

解决办法

升级jar包版本,回收动态代理类

延伸阅读

深入理解java虚拟机第二版

full gc后,仍有较大内存没有被回收

现象

老年代频繁full gc,每5小时一次,而且每次回收后总有1g左右的内存无法回收,
配置:-Xms2048m -Xmx4096m -XX:NewSize=512m -XX:MaxNewSize=512m

原因分析

当然,在发现问题就找运维要了dump,发现大量ThreadLocal中存有15M左右的日志数据,经过排查代码,发现是公司的日志
框架中,使用了ThreadLocal保存日志,使用完之后却没有remove,而是通过StringBuffer.setLength(0)来重置指针,
导致StringBuilder中字符数组的内存没有被清除,而由于使用线程池,所以内存一直无法释放。

解决办法

ThreadLocal.remove

延伸阅读

ThreadLocal原理篇

承接上面一个问题,修改之后full gc还是比较频繁

现象

full gc 由原来的5个小时/次,变成了15小时每次

原因分析

正常情况,老年代内存的产生有几种情况:

  1. 新生代GC后,超过eden存储大小的对象
  2. 大对象直接进入老年代
  3. 年龄到了设置值的对象
  4. 动态年龄判断,提前晋升

在请求量没有太大变化的情况下,一般都是大对象,大接口的问题,导致较多对象一直无法释放,或者直接进入老年代。
上面还有一个现象是,跟其他服务对比,该服务年轻带gc很不频繁,感觉就像是上面说的第二点,大对象直接进入
老年代了,所以同事让运维申请了内存,整体扩充一倍,老年代gc给缓下来了,在不改代码的情况下,似乎也没什么
特别好的方式了。。当然这里也问过为什么不是只升级新生代,连坐老年代感觉收益不大,没有得到很好的答复,
后面再问下。

解决办法

升级内存,当然这方法指标不治本,根本方法是修改代码,快速释放内存,修改调用方式,将查询全部的接口改为分页查询等

延伸阅读

深入理解java虚拟机第二版

事务系列

使用spring事务隔离级别死锁

现象

大量报错,提示获取不到数据库链接

原因分析

两个事务,外部事务隔离级别为REQUIRED,内部事务REQUIRES_NEW,由于内部和外部,都更新同一条数据,导致死锁

解决办法

都用REQUIRED

其他

iterator.hasNext 判断有值就continue

现象

集群中cpu使用率百分之一千,因为得不到时间,所以请求时间大量超时,线程得不到释放,所以又不听加线程

原因分析

这个是同事发现的问题,知道的时候已经有运维发现的线程dump了,线程状态RUNNABLE,运行到continue的位置,
那基本已经定位了。

解决办法

continue之前,先调用iterator.next();

延伸阅读

其实网上关于如何定位cpu占用率过高的帖子比较多,一年前遇到这个问题的时候还不知道怎么解决好,
CPU占用过高分析

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值