Java:ApacheHttpClient连接寿命(timeToLive)未配置问题分析

一、问题描述

若 Apache HttpClient 未设置 timeToLive,通过服务域名访问服务的实例并且服务域名解析出的 IP 发生变化时,在短时间内会有部分请求出现连接异常错误。

二、问题分析

Apache HttpClient 通过服务域名从连接池获取连接,当连接池没有连接可用时,会使用服务域名当前解析出的IP生成连接放入这个连接池。
正常情况下,Apache HttpClient 通过服务域名从连接池获取连接,此时获取到的连接的 IP 与服务域名当前解析的 IP 相同,HTTP请求正常。
当做单边切换时,一般会先将服务域名切换到新 IP 上,被调服务旧 IP 的实例会一般做优雅停机处理。但由于 Apache HttpClient 还是通过服务域名从连接池获取连接,此时获取到的连接仍然连的是服务旧 IP 的实例,一旦服务旧 IP 的实例下线,会导致部分 Apache HttpClient 发起的请求出现连接异常,然后 Apache HttpClient 会将这个异常连接销毁。当Apache HttpClient 随后发起请求时,由于从连接池中获取不到连接,会使用服务域名当前解析的 新IP 生成新的连接并放入连接池中,此时 HTTP 请求将恢复正常。

三、举例说明

正常情况下,服务域名解析采用就近路由方式,AZ1 下的服务 A 的实例使用 IP-1 访问 AZ1 下的服务 B 的实例,AZ2 下的服务 A 的实例使用 IP-2 访问 AZ2 下的服务 B 的实例。

当服务 B 在 AZ2 中的实例停单边后,AZ2 下的服务 A 的实例应使用 IP-1 访问 AZ1 下的服务 B 的实例,但 由于未设置 timeToLive 并且 A2 连接池中的连接仍然是以前的旧连接,当 LB2 停止时,这些连接会报连接异 常错误,如果此时有在途的交易,这些交易的就成了"结果未知的交易"。

四、解决方案

Apache HttpClient 设置 timeToLive,并设置 timeToLive < 服务优雅停机时间
当服务域名切换到新 IP 后,由于连接池中使用旧 IP 生成的连接会在服务旧 IP 的实例下线前销毁,所以在做单边切换时,不会在短时间内出现连接异常错误。

五、问题总结

1、通过此案例发现,优雅停机需要调用方和被调方都要实现一定的功能才能保证,只其中一方提供优雅停机功能并不能保证在停机过程中不出现"结果未知的交易"。
2、JDK 提供域名缓存功能,缓存时长默认为 60s,timeToLive 应小于域名缓存时长,保证缓存更新前旧的连接能及时销毁,总之,timeToLive 应满足如下条件

timeToLive < min(服务优雅停机时间, 域名缓存时长)

相关推荐
24k小善30 分钟前
Flink TaskManager详解
java·大数据·flink·云计算
想不明白的过度思考者36 分钟前
Java从入门到“放弃”(精通)之旅——JavaSE终篇(异常)
java·开发语言
.生产的驴1 小时前
SpringBoot 封装统一API返回格式对象 标准化开发 请求封装 统一格式处理
java·数据库·spring boot·后端·spring·eclipse·maven
猿周LV1 小时前
JMeter 安装及使用 [软件测试工具]
java·测试工具·jmeter·单元测试·压力测试
晨集1 小时前
Uni-App 多端电子合同开源项目介绍
java·spring boot·uni-app·电子合同
时间之城1 小时前
笔记:记一次使用EasyExcel重写convertToExcelData方法无法读取@ExcelDictFormat注解的问题(已解决)
java·spring boot·笔记·spring·excel
椰羊~王小美1 小时前
LeetCode -- Flora -- edit 2025-04-25
java·开发语言
凯酱1 小时前
MyBatis-Plus分页插件的使用
java·tomcat·mybatis
程序员总部2 小时前
如何在IDEA中高效使用Test注解进行单元测试?
java·单元测试·intellij-idea
oioihoii2 小时前
C++23中if consteval / if not consteval (P1938R3) 详解
java·数据库·c++23