java.net.SocketTimeoutException:超时。连接池空闲超时已过期。没有可用的连接。
java.net.SocketTimeoutException: timeout. ConnectionPool idle timeout expired. No connection available.
ID: android/okhttp-connection-pool-timeout
版本兼容性
| 版本 | 状态 | 引入 | 弃用 | 备注 |
|---|---|---|---|---|
| OkHttp 4.11.0 | active | — | — | — |
| OkHttp 4.12.0 | active | — | — | — |
| Android 13 (API 33) | active | — | — | — |
根因分析
OkHttp 的连接池在空闲超时(默认 5 分钟)后没有可重用的空闲连接,并且由于网络问题或服务器不可用,无法在配置的连接超时内建立新连接。
English
OkHttp's connection pool has no idle connections available for reuse after the idle timeout (default 5 minutes), and a new connection cannot be established within the configured connect timeout due to network issues or server unavailability.
官方文档
https://square.github.io/okhttp/4.x/okhttp/okhttp3/-connection-pool/解决方案
-
Increase the idle timeout and pool size in OkHttpClient: `val client = OkHttpClient.Builder().connectionPool(ConnectionPool(10, 10, TimeUnit.MINUTES)).connectTimeout(15, TimeUnit.SECONDS).build()`
-
Implement retry logic with exponential backoff in your network call: `retryWhen { cause, attempt -> if (cause is SocketTimeoutException && attempt < 3) { delay((1000L * Math.pow(2.0, attempt.toDouble())).toLong()) true } else false }` (Kotlin coroutines example).
无效尝试
常见但无效的做法:
-
90% 失败
The error is about connection pool idle timeout, not connect timeout. Increasing connect timeout does not prevent pool exhaustion; it only delays the failure.
-
75% 失败
Disabling pooling forces a new connection for every request, which can cause performance degradation and increase the likelihood of timeout errors under load.