记一次三方组件封装不当导致的OOM
原创2019/4/9大约 1 分钟
记一次三方组件封装不当导致的OOM
1、业务背景
Spring Cloud 微服务架构在一个二方库项目中,基于 jedis 客户端和 hutool 的 RedisDS 模块进行了二次封装,即一个 RedisUtil 类。
2、问题现象
后台请求超时,数据列表为空
用户端 nginx 运行一段时间会报错
重启服务后问题解决,运行一段时间问题复现
3、排查过程
(略)
4、定位原因
创建并使用原生 jedis 对象后,未调用 close 方法释放连接,导致对象越来越多,最终爆发:
java.lang.OutOfMemoryError: GC overhead limit exceeded调用方法时每次都 new 了一个 RedisDS 对象(非直接原因,只是不太合适),如下:
public static Jedis getJedis() {
try {
RedisDS redisDS = RedisDS.create(REDIS_CONFIG, null);
return redisDS.getJedis();
} catch (Exception e) {
log.error("Redis连接异常!", e);
return null;
}
}5、解决方案
在使用完 jedis 对象后释放连接
public static void close(Jedis jedis) {
if (jedis != null) {
jedis.close();
}
}将 RedisDS 对象定义为 static 成员变量,仅初始化一次即可
6、总结经验
使用第三方组件有可能造成内存泄露
访问外部资源记得释放
不正确的单例模式
不合理的类结构:A引用B,B引用C,C引用A

