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

IT 文章2年前 (2023)发布 小编
0 0 0

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

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

现象

这是一个Java 应用, 有监控它的线程总数, 各个服务器的线程总数看上去是这个样子的:排查解决大量创建连接池导致的线程泄漏问题

ad

程序员导航

优网导航旗下整合全网优质开发资源,一站式IT编程学习与工具大全网站

查看不断增长的线程

通过thread dump, 我们可以看到里面包含居多以 Connection evictor命名的线程, 如下:排查解决大量创建连接池导致的线程泄漏问题

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

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

验证推断

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

ad

AI 工具导航

优网导航旗下AI工具导航,精选全球千款优质 AI 工具集

$ 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),学习愉快哦![readsource]https://juejin.cn/post/7310423470546272319[/readsource]

ad

免费在线工具导航

优网导航旗下整合全网优质免费、免注册的在线工具导航大全

© 版权声明

相关文章

暂无评论

暂无评论...