重复Transfer-Encoding响应头引发客户端异常,求Spring Boot场景解决方案
分块编码响应损坏问题:重复Transfer-Encoding头导致客户端IOException
问题场景
- 存在三个Spring Boot服务:Client、Proxy、API,Client通过Proxy转发请求调用API
- 约1%的响应出现损坏,客户端抛出异常:
java.io.IOException: Illegal character in chunk size: 123
错误原因分析
- 该异常表明响应采用分块编码(chunked),但缺失块大小标识,直接以JSON对象的起始符
{(十六进制值为123)开头 - 客户端收到
Transfer-Encoding: chunked响应头,要求按分块规则读取响应,但因缺少块大小信息,无法解析响应从而抛出异常
排查过程
- 检查Proxy转发后的API响应头,发现存在重复的
Transfer-Encoding头 - API端逻辑:当返回动态内容(如来自数据库的数据)时,Spring/Tomcat无法预先确定内容长度,会自动启用分块编码并添加
Transfer-Encoding头 - Proxy端问题:Proxy的头转换代码中,
okttp3Headers.names()是集合类型,不会产生重复头,但Proxy内部的Tomcat会额外添加一次Transfer-Encoding头,疑似Tomcat bug;升级Spring Boot/Tomcat至最新版本后问题仍未解决 - 复现条件:仅在负载场景下可复现,例如300次请求中约出现3-4次错误
- 临时方案:在API端手动移除
Transfer-Encoding头(此时会自动添加Content-Length头)可解决问题,但该方案并非合理的长期解决方案
Proxy相关代码片段
Proxy使用OkHttpClient实现请求转发,以下是处理请求并转换响应头的代码:
... return new ResponseEntity<>( responseBodyString, convertHeaders(forwarderRequestResponse.headers()), Objects.requireNonNull(HttpStatus.resolve(forwarderRequestResponse.code()))); } public HttpHeaders convertHeaders(Headers okttp3Headers) { var headers = new HttpHeaders(); for (String headerName : okttp3Headers.names()) { for (String headerValue : okttp3Headers.values(headerName)) { headers.add(headerName, headerValue); } } return headers; }
求助
请分享相关问题处理经验或提供合理的解决方案。
内容的提问来源于stack exchange,提问作者Ilja Veselov
相关产品推荐
相关产品推荐

