OkHttp3多线程认证代理请求报Address already in use异常求解
问题根因
java.net.BindException: Address already in use 触发的直接原因是本机临时端口耗尽,和你用的HTTPS代理、Basic认证、信任所有证书的SSL配置没有直接关系。
你描述的“累计10000-15000次请求后触发”完全符合短连接泄露导致端口耗尽的特征:TCP连接主动关闭后会进入TIME_WAIT状态,默认会占用端口120秒才会释放,短时间内大量创建不被复用的短连接,很快就会把系统可用的临时端口占满,新的连接无法绑定本地端口就会抛出这个异常。
核心排查修复点
1. 确认OkHttpClient是否全局单例
OkHttpClient官方明确要求全局复用,每个实例内部维护独立的连接池、线程池、调度器。如果你的getClient()方法每次调用都重新执行build()创建新实例:
- 连接池完全失效,每次请求都要新建到代理的TCP连接
- 旧实例关联的连接关闭后全部进入TIME_WAIT状态占用端口
- 累计1万多次请求后端口被占满,和你遇到的触发阈值完全吻合
修复方式:将OkHttpClient初始化为应用全局单例,所有请求复用同一个实例。
2. 确认Response被正确关闭
你贴出的请求代码只调用了execute()获取Response,没有做关闭处理。OkHttp同步请求的Response必须显式关闭,否则对应的连接不会被回收到连接池,会直接泄露,永远无法被复用。
错误写法:
Response response = getClient().newCall(builder.build()).execute(); // 处理响应逻辑,没有关闭操作,连接泄露
正确写法,用try-with-resources保证资源释放:
try (Response response = getClient().newCall(builder.build()).execute()) { // 在此处读取响应、处理业务逻辑 if (!response.isSuccessful()) { // 错误处理 } }
可选优化项
修复上述两个问题后如果仍有偶发端口占用,可以调整OkHttp连接池配置,加速空闲连接回收:
// 自定义连接池:最多保留20个空闲连接,空闲超过1分钟就自动回收 builder.connectionPool(new ConnectionPool(20, 1, TimeUnit.MINUTES));
高并发场景下也可以配合调整操作系统参数,扩大临时端口范围、开启TIME_WAIT端口快速复用,但代码层面的单例复用、资源关闭是必须先修复的核心问题,99%的同类报错都是这两个原因导致的。
内容的提问来源于stack exchange,提问作者sgjaujkda
相关产品推荐
相关产品推荐

