bigywater.tech
Java · 254

网络超时分类:连接、读取和整体截止时间

连接超时、读超时、请求超时、总截止时间——它们是不同的东西,混用会让请求悄悄卡住很久。这篇用真实的服务器,逐个验证每种超时到底管什么、不管什么。

4120 ms
服务器每 200 ms 滴一个字节时,setSoTimeout(500) 完全没触发的总读取时间
3 ms
端口没人监听时 Connection refused 的耗时(与超时参数无关)
响应头
HttpRequest.timeout 实际生效的范围

连接超时

实测 · 本机执行输出
  连接超时用 RFC 5737 保留的文档地址 192.0.2.1:80(TEST-NET-1,没有任何真实主机,SYN 发出去没有回应)测试;macOS 回环上让监听队列满了得到的是 Connection reset 而不是超时,所以不用本机端口
  Socket.connect(…, 500 ms) → SocketTimeoutException: Connect timed out,耗时 522 ms
  本机端口没有人监听 → ConnectException: Connection refused,耗时 3 ms(立刻失败,与超时无关)
  HttpClient connectTimeout(500 ms) → http.HttpConnectTimeoutException: HTTP connect timed out,耗时 527 ms
  HttpClient,本机端口没有人监听 → ConnectException: null,耗时 3 ms
  非阻塞 SocketChannel.connect:立即完成 = false;select(500 ms) 返回就绪数 0,耗时 502 ms(没有就绪就是超时了,要自己 close 这个 channel)

读超时 SO_TIMEOUT

实测 · 本机执行输出
  服务器接受连接但不回应,setSoTimeout(300) → SocketTimeoutException: Read timed out,耗时 319 ms
  服务器每 200 ms 滴一个字节、共 20 个字节:setSoTimeout(500) 没有触发,读完 20 字节,总耗时 4144 ms(每次 read 各自计时,总时间 4 s 远超 500 ms)
  setSoTimeout(150),服务器间隔 200 ms → SocketTimeoutException: Read timed out,耗时 153 ms
  自己实现总截止时间:每次 read 前把 SO_TIMEOUT 设成剩余时间 → SocketTimeoutException: Read timed out,耗时 1002 ms

HttpClient 与整体截止时间

实测 · 本机执行输出
  HttpRequest.timeout(500 ms),服务器 1.5 s 后才发响应头 → http.HttpTimeoutException: request timed out,耗时 512 ms
  HttpRequest.timeout(500 ms),响应头立即到、body 每 200 ms 一个字节共 15 个(总 3 s):读完 15 字节,耗时 3142 ms(超时只管到响应头)
  sendAsync(…).orTimeout(1 s) 包住整个响应读取 → java.util.concurrent.TimeoutException: null,耗时 1012 ms
  没有设置 timeout:等了 1512 ms 拿到响应(默认没有超时)
  Future.get(300 ms) 超时 → TimeoutException,耗时 301 ms;任务仍在跑:isDone = false(get 超时不会取消任务,要自己 cancel(true))

分步演示

网络超时
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / OpenJDK(Temurin 17.0.20、Homebrew 21.0.12 与 27,每篇注明实际用的版本);用 javac 编译、java 直接运行,需要第三方库时用 Maven 解析依赖;计时用 System.nanoTime,数字每次运行会有小幅抖动。JDK 21.0.12,macOS;连接超时用 RFC 5737 的文档地址 192.0.2.1(只发出 SYN,没有真实主机);其它用 127.0.0.1 的本机服务器
    • 没有验证:DNS 解析超时(没有测)、TLS 握手超时(HttpClient 的 connectTimeout 是否包含)、Linux 的 TCP 重传与默认连接超时、代理环境下的超时、HTTP/2 流的超时、连接池里空闲连接的超时
    京ICP备2026067502号-1京公网安备11010502063487号