如何在Spring WS中使用Apache HTTP连接池管理器?连接未复用问题排查
Spring WS中Apache HTTP连接池无法复用问题排查
我在Spring WS中使用Apache HTTP连接池管理器时,遇到连接已被池化但无法复用的问题,相关情况及日志如下:
连接似乎已被池化但未被复用
连接复用情况...
2022-11-24 21:08:50,934 [ReceiveDepth:1] DEBUG org.apache.http.impl.conn.PoolingHttpClientConnectionManager - 连接请求: [路由: {s}->https://services.mybank.nl:18290][总可用连接数: 4; 路由已分配连接数: 4/4; 总已分配连接数: 4/4] 2022-11-24 21:08:50,934 [ReceiveDepth:1] DEBUG org.apache.http.impl.conn.DefaultManagedHttpClientConnection - http-outgoing-0: 关闭连接 2022-11-24 21:08:50,941 [ReceiveDepth:1] DEBUG org.apache.http.impl.conn.PoolingHttpClientConnectionManager - 租赁连接: [ID: 4][路由: {s}->https://services.mybank.nl:18290][总可用连接数: 3; 路由已分配连接数: 4/4; 总已分配连接数: 4/4] 2022-11-24 21:08:50,941 [ReceiveDepth:1] DEBUG org.apache.http.impl.execchain.MainClientExec - 打开连接 {s}->https://services.mybank.nl:18290 2022-11-24 21:08:50,941 [ReceiveDepth:1] DEBUG org.apache.http.impl.conn.DefaultHttpClientConnectionOperator - 连接到 services.mybank.nl/10.239.166.11:18290 2022-11-24 21:08:50,969 [ReceiveDepth:1] DEBUG org.apache.http.impl.conn.DefaultHttpClientConnectionOperator - 连接已建立 10.239.148.30:33114<->10.239.166.11:18290 2022-11-24 21:08:50,969 [ReceiveDepth:1] DEBUG org.apache.http.impl.execchain.MainClientExec - 执行请求 POST /migrate HTTP/1.1 2022-11-24 21:08:50,969 [ReceiveDepth:1] DEBUG org.apache.http.impl.execchain.MainClientExec - 目标认证状态: 未挑战 2022-11-24 21:08:50,969 [ReceiveDepth:1] DEBUG org.apache.http.impl.execchain.MainClientExec - 代理认证状态: 未挑战 2022-11-24 21:08:50,983 [ReceiveDepth:1] DEBUG org.apache.http.impl.execchain.MainClientExec - 连接可无限期保持存活 2022-11-24 21:08:50,984 [ReceiveDepth:1] DEBUG org.apache.http.impl.conn.PoolingHttpClientConnectionManager - 连接 [ID: 4][路由: {s}->https://services.mybank.nl:18290][状态: CN=rc-uat3.rf.mybank.nl, OU=BSRC Groep ICT, O=Cooperatieve Mybank U.A., L=Utrecht, ST=Utrecht, C=NL] 可无限期保持存活 2022-11-24 21:08:50,984 [ReceiveDepth:1] DEBUG org.apache.http.impl.conn.DefaultManagedHttpClientConnection - http-outgoing-4: 设置套接字超时为0 2022-11-24 21:08:50,984 [ReceiveDepth:1] DEBUG org.apache.http.impl.conn.PoolingHttpClientConnectionManager - 连接已释放: [ID: 4][路由: {s}->https://services.mybank.nl:18290][状态: CN=rc-uat3.rf.mybank.nl, OU=BSRC Groep ICT, O=Cooperatieve Mybank U.A., L=Utrecht, ST=Utrecht, C=NL][总可用连接数: 4; 路由已分配连接数: 4/4; 总已分配连接数: 4/4]
问题分析
从日志能看出核心矛盾:连接池已持有可用连接,但新请求仍需重新建立连接,而非复用池内连接。关键细节包括:
- 请求发起时,路由连接数已达上限(4/4),随即有旧连接被关闭
- 租赁到ID为4的连接后,日志显示需要重新打开并建立新连接,说明该连接并非池内已有的存活连接
- 连接使用后被标记为可无限期存活并释放回池,但后续请求未复用
解决方向
- 确保连接正确释放:检查Spring WS客户端是否在请求完成后将连接归还给池。使用
CloseableHttpClient时需在finally块中关闭,或确认Spring WS的HttpComponentsMessageSender配置正确管理连接生命周期。 - 优化连接池配置:
- 调整
PoolingHttpClientConnectionManager的setMaxTotal(总最大连接数)和setDefaultMaxPerRoute(单路由最大连接数)参数,避免因路由连接数耗尽导致频繁关闭旧连接 - 设置
setValidateAfterInactivity,让连接池在复用空闲连接前验证其有效性,避免使用已被服务端断开的连接
- 调整
- 检查服务端长连接支持:确认目标服务端响应头包含
Connection: keep-alive,若服务端主动关闭连接,客户端无法复用 - 配置空闲连接清理:添加
IdleConnectionEvictor定期清理池内空闲超时的无效连接,示例代码:
@Bean public CloseableHttpClient httpClient() { PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(); connectionManager.setMaxTotal(20); connectionManager.setDefaultMaxPerRoute(4); connectionManager.setValidateAfterInactivity(5000); // 启动空闲连接清理器 IdleConnectionEvictor evictor = new IdleConnectionEvictor(connectionManager, 1, TimeUnit.MINUTES, 5, TimeUnit.SECONDS); evictor.start(); return HttpClientBuilder.create() .setConnectionManager(connectionManager) .build(); }
- 验证Spring WS客户端配置:确保自定义的
PoolingHttpClientConnectionManager被正确注入到HttpComponentsMessageSender中,替代默认连接管理器。
内容的提问来源于stack exchange,提问作者Kevin Hancock
相关产品推荐
相关产品推荐

