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(服务优雅停机时间, 域名缓存时长)

相关推荐
信仰_27399324310 分钟前
RocketMQ事务消息实现订单创建 + 扣减库存
java·rocketmq·java-rocketmq
百***581411 分钟前
Spring Boot 2.7.x 至 2.7.18 及更旧的版本,漏洞说明
java·spring boot·后端
q***64971 小时前
Spring BOOT 启动参数
java·spring boot·后端
百***78451 小时前
Java实战:Spring Boot application.yml配置文件详解
java·网络·spring boot
你不是我我1 小时前
【Java 开发日记】SQL 语句左连接右连接内连接如何使用,区别是什么?
java·javascript·数据库
七夜zippoe1 小时前
Java性能调优工具篇:JMH基准测试与Profiler(JProfiler/Async-Profiler)使用指南
java·开发语言·jprofiler·jmh·async-profiler
從南走到北1 小时前
JAVA国际版二手车交易二手车市场系统源码支持Android+IOS+H5+APP
android·java·ios
Kuo-Teng2 小时前
LeetCode 19: Remove Nth Node From End of List
java·数据结构·算法·leetcode·链表·职场和发展·list
北i2 小时前
TiDB 关联子查询去关联优化实战案例与原理深度解析
java·数据库·sql·tidb
Kuo-Teng2 小时前
LeetCode 21: Merge Two Sorted Lists
java·算法·leetcode·链表·职场和发展