排查解决大量创建连接池导致的线程泄漏问题

后端 潘老师 5个月前 (12-10) 160 ℃ (0) 扫码查看

本文主要讲解关于如何排查解决大量创建连接池导致的线程泄漏问题相关内容,让我们来一起学习下吧!

对的, 你没看错, 大量创建连接池, 连接是稳定的, 但是却导致线程暴涨.

现象

这是一个Java 应用, 有监控它的线程总数, 各个服务器的线程总数看上去是这个样子的:

查看不断增长的线程

通过thread dump, 我们可以看到里面包含居多以 Connection evictor命名的线程, 如下:

还碰巧看到一个正在做事的线程栈, 从这里我们可以大概猜出这是 Apache httpClient 的连接池, 它正在清理长期不用的连接.

我们推测这个应用在不断的创建连接池, 然后就抛弃不用, 然后就该 Connection evictor 出场来清理这些不再被使用的连接.

验证推断

既然推断创建了很多连接池, 那么我们就来看看到底有多少连接池.

$ jcmd 2447856 GC.class_histogram | grep PoolingHttpClientConnectionManager
 223:           3211          101568  org.apache.http.impl.conn.PoolingHttpClientConnectionManager
 224:           3211          101568  org.apache.http.impl.conn.PoolingHttpClientConnectionManager$ConfigData
 284:           3211          86176  org.apache.http.impl.conn.PoolingHttpClientConnectionManager$InternalConnectionFactory

上面第二列的输出表示有多少这样的对象, 不出所料, 果然有这么多连接池.

找出真凶, 哪里创建这么多连接池

既然创建这么多 PoolingHttpClientConnectionManager 对象, 那么就看看到底哪里新建的这些对象吧. 使用 Btrace 工具, 使用如下Btrace 脚本:

import org.openjdk.btrace.core.annotations.*;
import static org.openjdk.btrace.core.BTraceUtils.*;
 
import org.openjdk.btrace.core.BTraceUtils.Strings;
 
@BTrace
public class ConnectionPoolTracer {
 
    @OnMethod( clazz="/org\.apache\.http\.impl\.conn\.PoolingHttpClientConnectionManager/", method="<init>" )
    public static void createPool() {
        println(Strings.strcat("current thread: ", name(currentThread())));
        println(jstackStr());
    }
}

去执行, 得到如下栈:

org.apache.http.impl.conn.PoolingHttpClientConnectionManager.<init>(PoolingHttpClientConnectionManager.java:165)
org.apache.http.impl.client.HttpClientBuilder.build(HttpClientBuilder.java:988)
org.tianxiaohui.utils.HttpConnectionUtils.getHttpConnection(HttpConnectionUtils.java:56)
org.tianxiaohui.utils.HttpUtils.createClientWithSSL(HttpUtils.java:144)
org.tianxiaohui.utils.HttpUtils.createClientWithSSL(HttpUtils.java:128)
org.tianxiaohui.service.CustomProperties.getVariable(CustomProperties.java:1133)

原来是每次调用 HttpConnectionUtils.getHttpConnection() 这个方法, 就会创建一个新的连接池.

修复

全局共享的一个连接池.

以上就是关于如何排查解决大量创建连接池导致的线程泄漏问题相关的全部内容,希望对你有帮助。欢迎持续关注潘子夜个人博客(www.panziye.com),学习愉快哦!


版权声明:本站文章,如无说明,均为本站原创,转载请注明文章来源。如有侵权,请联系博主删除。
本文链接:https://www.panziye.com/back/12428.html
喜欢 (0)
请潘老师喝杯Coffee吧!】
分享 (0)
用户头像
发表我的评论
取消评论
表情 贴图 签到 代码

Hi,您需要填写昵称和邮箱!

  • 昵称【必填】
  • 邮箱【必填】
  • 网址【可选】