OkHttp连接Spring Boot Stomp WebSocket重连报400错误问题咨询
问题诱因
- OkHttp默认连接池复用失效TCP连接:OkHttpClient默认连接池最大保留5个空闲TCP连接,存活时间为5分钟。WebSocket应用层关闭后,底层TCP连接未被回收会存入连接池,后续新的WebSocket握手请求复用这些已被服务端判定为无效的旧TCP连接时,服务端会直接返回400错误,且请求不会触发Spring的握手拦截器。你遇到的前3-4次重连正常、之后持续报错的现象,刚好匹配默认连接池的最大空闲连接数阈值。
- 关闭逻辑时序错误:调用
socket.close()是异步操作,你在调用关闭后立刻发起新连接,此时旧WebSocket关联的TCP连接还未完成释放,会残留到连接池中。 - (可选)请求URL不规范:你示例代码中的WebSocket URL未添加
ws:///wss://协议前缀,会导致OkHttp错误复用普通HTTP连接池的连接发起Upgrade请求,也会触发400错误。
解决方案
- 补全请求URL协议前缀,同时给WebSocket请求禁用连接复用:
val webSocketRequest = Request.Builder() .url("ws://199.166.1.100:8081/websocket") // 补全ws协议头 .addHeader("Connection", "close") // 强制每次握手使用新的TCP连接,不复用连接池资源 .build()
- 给WebSocket专用的OkHttpClient单独配置连接池,直接禁用空闲连接保留:
// 初始化WebSocket专属OkHttpClient,不复用TCP连接 val wsOkHttpClient = OkHttpClient.Builder() .connectionPool(ConnectionPool(0, 1, TimeUnit.NANOSECONDS)) // 空闲连接数为0,立即回收失效连接 .build()
- 调整重连触发时机:不要在调用
socket.close()后立刻发起新连接,将重连逻辑放到onClosed回调中执行,确保旧连接资源完全释放后再发起新的握手请求。 - 可选升级OkHttp版本到4.10.0及以上,规避旧版本WebSocket连接管理的已知bug。
内容的提问来源于stack exchange,提问作者KisungTae
相关产品推荐
相关产品推荐

