fix(rustfs): 修 unexpected end of stream 根因——零长度请求体缺 Content-Length
抓包定位(90 秒内 515 次 HTTP 411 Length Required):OkHttp 对长度为 0 的请求体 不写 Content-Length,请求于是既无 Content-Length 也无 Transfer-Encoding——HTTP/1.1 不允许这样,RustFS 直接回 411;客户端读到不完整响应就报 unexpected end of stream 再重试。业务里上传空内容(content 为 null/空)是常态,所以每天上千次。 修复用 network interceptor 在协议层补 Content-Length: 0:普通 interceptor 里加的 头会被 BridgeInterceptor 按 body 长度覆盖,加了不生效。 实测:部署后同样 90 秒抓包,411 从 515 次降到 0,两节点「确定性错误不重试」归零。 此前排除的公网链路、keepAlive、连接复用三项确实都不是原因——抓包才是对的入口。
This commit is contained in:
+16
@@ -382,6 +382,22 @@ public class RustfsObjectStorageService {
|
||||
Math.max(1L, properties.getConnectionPoolKeepAliveMillis()),
|
||||
TimeUnit.MILLISECONDS))
|
||||
.retryOnConnectionFailure(true)
|
||||
.addNetworkInterceptor(chain -> {
|
||||
okhttp3.Request request = chain.request();
|
||||
okhttp3.RequestBody body = request.body();
|
||||
// OkHttp 对「长度为 0 的请求体」不会写 Content-Length,于是请求既无
|
||||
// Content-Length 也无 Transfer-Encoding(HTTP/1.1 不允许这样)。
|
||||
// RustFS 对此直接回 411 Length Required,客户端读到不完整响应就报
|
||||
// unexpected end of stream,进而重试——线上抓包实测 90 秒内 515 次 411,
|
||||
// 而上传空内容(content 为 null/空)在业务里是常态。
|
||||
// 用 network interceptor 在协议层补上该头(普通 interceptor 会被
|
||||
// BridgeInterceptor 按 body 长度覆盖掉,加了也不生效)。
|
||||
if (body != null && body.contentLength() == 0L
|
||||
&& request.header("Content-Length") == null) {
|
||||
request = request.newBuilder().header("Content-Length", "0").build();
|
||||
}
|
||||
return chain.proceed(request);
|
||||
})
|
||||
.build();
|
||||
}
|
||||
return httpClient;
|
||||
|
||||
Reference in New Issue
Block a user