尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
一次现网问题定位-接口偶发报500,PrematureCloseException: Connection prematurely closed DURING response
背景本系统做改造使用spring cloud gateway替换nginx作为反向代理。如上图所示系统整体网络结构未有变化仅仅只是使用api-gateway(使用spring cloud gateway开发的)替换掉nginx作为反向代理。替换的原因这里就不做介绍了。系统上线后监控到接口偶发报500api-gateway有报错日志(仅api-gateway报错微服务无报错)。2025-07-26 12:16:11,101 [reactor-http-nio-4] ERROR o.s.b.a.w.r.e.AbstractErrorWebExceptionHandler - [548c5657-249824] 500 Server Error for HTTP GET “/hoss-gateway/api/platform/tenants/35/getBusinessWorkTime”reactor.netty.http.client.PrematureCloseException: Connection prematurely closed DURING responseSuppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException:Error has been observed at the following site(s):*__checkpoint ⇢ org.springframework.cloud.gateway.filter.WeightCalculatorWebFilter [DefaultWebFilterChain]*__checkpoint ⇢ com.huawei.cbgservice.hoss.apigateway.filter.CorsWebFilter [DefaultWebFilterChain]*__checkpoint ⇢ com.huawei.cbgservice.hoss.apigateway.filter.UrlInterceptorWebFilter [DefaultWebFilterChain]*__checkpoint ⇢ HTTP GET “/hoss-gateway/api/platform/tenants/35/getBusinessWorkTime” [ExceptionHandlingWebHandler]Original Stack Trace:处理过程尝试快速修复使用关键字reactor.netty.http.client.PrematureCloseException: Connection prematurely closed DURING response搜索google搜到的都是Connection prematurely closed BEFORE response。里面给的解决方案基本上就是配置连接池相关参数spring.cloud.gateway.httpclient.pool.eviction-intervalxxspring.cloud.gateway.httpclient.pool.max-idle-timexx虽然两个报错有些区别不过看配置是解决连接池失效的问题有可能能行因此先配置上去看能否解决问题。结果不行深入定位过程从报错来看跟业务无关像是网络层有问题。使用关键字“Connection prematurely closed DURING response”搜索代码发现有2个地方。最终分析应该是HttpClientOperations中报的错。因为dev环境没办法复现没办法通过断点调试确认问题另外reactor-netty代码比较难理解难以通过快速阅读源码确认可疑点。只能尝试去探寻报错时连接处于一个什么样的状态是发送完请求后开始读取响应时报错了还是读取完了响应头报错了还是是其他什么状况连接有没有正常关闭通过日志获取相关信息刚开始时只是打开debug日志此时并未获取到可用的信息后面在分析客户端配置时发现有配置(spring.cloud.gateway.httpclient.wiretaptrue)能够开启对http交互过程的记录,遂开启后抓取以下日志可见作者写http相关组件时也是遇到了跟报文解析相关的问题。不然要是不记录http报文交互过程出了问题后很难知道当时发生了什么。2025-07-25 17:39:11,256 [reactor-http-nio-1] DEBUG r.n.r.DefaultPooledConnectionProvider - [edfa632a-82, L:/x.x.x.x:50014 - R:/x.x.x.x:55482] onStateChange(POST{uri/api/platform/tenants/35/rest/channels/14285, connectionPooledConnection{channel[id: 0xedfa632a, L:/x.x.x.x:50014 - R:/x.x.x.x:55482]}}, [request_sent]) 2025-07-25 17:39:11,268 [reactor-http-nio-1] DEBUG reactor.netty.http.client.HttpClient - [edfa632a-82, L:/x.x.x.x:50014 - R:/x.x.x.x:55482] READ: 452B ------------------------------------------------- | 0 1 2 3 4 5 6 7 8 9 a b c d e f | ------------------------------------------------------------------------- |00000000| 48 54 54 50 2f 31 2e 31 20 32 30 30 20 0d 0a 63 |HTTP/1.1 200 ..c| |00000010| 6f 6e 6e 65 63 74 69 6f 6e 3a 20 63 6c 6f 73 65 |onnection: close| |00000020| 0d 0a 64 61 74 65 3a 20 46 72 69 2c 20 32 35 20 |..date: Fri, 25 | |00000030| 4a 75 6c 20 32 30 32 35 20 30 39 3a 33 39 3a 31 |Jul 2025 09:39:1| |00000040| 31 20 47 4d 54 0d 0a 74 72 61 6e 73 66 65 72 2d |1 GMT..transfer-| |00000050| 65 6e 63 6f 64 69 6e 67 3a 20 63 68 75 6e 6b 65 |encoding: chunke| |00000060| 64 0d 0a 43 6f 6e 74 65 6e 74 2d 54 79 70 65 3a |d..Content-Type:| |00000070| 20 61 70 70 6c 69 63 61 74 69 6f 6e 2f 6a 73 6f | application/jso| |00000080| 6e 3b 63 68 61 72 73 65 74 3d 55 54 46 2d 38 0d |n;charsetUTF-8.| |00000090| 0a 0d 0a 7b 22 73 74 61 74 75 73 22 3a 22 4f 4b |...{status:OK| |000000a0| 22 2c 22 65 72 72 6f 72 43 6f 64 65 22 3a 6e 75 |,errorCode:nu| |000000b0| 6c 6c 2c 22 65 72 72 6f 72 44 65 73 63 72 69 70 |ll,errorDescrip| |000000c0| 74 69 6f 6e 22 3a 6e 75 6c 6c 2c 22 65 6e 74 69 |tion:null,enti| |000000d0| 74 69 65 73 22 3a 5b 7b 22 6b 65 79 22 3a 22 41 |ties:[{key:A| |000000e0| 73 79 6e 63 43 68 61 74 55 6e 72 65 73 6f 6c 76 |syncChatUnresolv| |000000f0| 65 64 50 72 69 6f 72 69 74 79 4d 69 6e 22 2c 22 |edPriorityMin,| |00000100| 76 61 6c 75 65 22 3a 22 31 32 30 22 7d 2c 7b 22 |value:120},{| |00000110| 6b 65 79 22 3a 22 41 73 79 6e 63 43 68 61 74 45 |key:AsyncChatE| |00000120| 6e 71 75 69 72 79 54 69 6d 65 4c 69 6d 69 74 48 |nquiryTimeLimitH| |00000130| 6f 75 72 22 2c 22 76 61 6c 75 65 22 3a 22 34 38 |our,value:48| |00000140| 22 7d 5d 2c 22 65 6e 74 69 74 79 22 3a 6e 75 6c |}],entity:nul| |00000150| 6c 2c 22 66 69 72 73 74 22 3a 6e 75 6c 6c 2c 22 |l,first:null,| |00000160| 6c 61 73 74 22 3a 6e 75 6c 6c 2c 22 73 69 7a 65 |last:null,size| |00000170| 22 3a 6e 75 6c 6c 2c 22 6e 75 6d 62 65 72 22 3a |:null,number:| |00000180| 6e 75 6c 6c 2c 22 6e 75 6d 62 65 72 4f 66 45 6c |null,numberOfEl| |00000190| 65 6d 65 6e 74 73 22 3a 6e 75 6c 6c 2c 22 74 6f |ements:null,to| |000001a0| 74 61 6c 50 61 67 65 73 22 3a 6e 75 6c 6c 2c 22 |talPages:null,| |000001b0| 74 6f 74 61 6c 45 6c 65 6d 65 6e 74 73 22 3a 6e |totalElements:n| |000001c0| 75 6c 6c 7d |ull} | ------------------------------------------------------------------------- 2025-07-25 17:39:11,268 [reactor-http-nio-1] DEBUG r.n.http.client.HttpClientOperations - [edfa632a-82, L:/x.x.x.x:50014 - R:/x.x.x.x:55482] Received response (auto-read:false) : RESPONSE(decodeResult: success, version: HTTP/1.1) HTTP/1.1 200 connection: filtered date: filtered transfer-encoding: filtered Content-Type: filtered 2025-07-25 17:39:11,268 [reactor-http-nio-1] DEBUG r.n.r.DefaultPooledConnectionProvider - [edfa632a-82, L:/x.x.x.x:50014 - R:/x.x.x.x:55482] onStateChange(POST{uri/api/platform/tenants/35/rest/channels/14285, connectionPooledConnection{channel[id: 0xedfa632a, L:/x.x.x.x:50014 - R:/x.x.x.x:55482]}}, [response_received]) 2025-07-25 17:39:11,268 [reactor-http-nio-1] DEBUG reactor.retry.DefaultRepeat - Stopping repeats since predicate returned false, retry context: iteration1 repeatCompanionValue0 backoff{0ms} 2025-07-25 17:39:11,268 [reactor-http-nio-1] DEBUG reactor.netty.channel.FluxReceive - [edfa632a-82, L:/x.x.x.x:50014 - R:/x.x.x.x:55482] [terminatedfalse, cancelledfalse, pending0, errornull]: subscribing inbound receiver 2025-07-25 17:39:11,268 [reactor-http-nio-1] DEBUG reactor.netty.http.client.HttpClient - [edfa632a-82, L:/x.x.x.x:50014 - R:/x.x.x.x:55482] READ COMPLETE 2025-07-25 17:39:11,268 [reactor-http-nio-1] DEBUG reactor.netty.http.client.HttpClient - [edfa632a-82, L:/x.x.x.x:50014 - R:/x.x.x.x:55482] READ COMPLETE 2025-07-25 17:39:11,268 [reactor-http-nio-1] DEBUG r.n.r.PooledConnectionProvider - [edfa632a-82, L:/x.x.x.x:50014 ! R:/x.x.x.x:55482] Channel closed, now: 0 active connections, 6 inactive connections and 0 pending acquire requests. 2025-07-25 17:39:11,268 [reactor-http-nio-1] DEBUG reactor.netty.http.client.HttpClient - [edfa632a-82, L:/x.x.x.x:50014 ! R:/x.x.x.x:55482] INACTIVE 2025-07-25 17:39:11,268 [reactor-http-nio-1] DEBUG r.n.r.DefaultPooledConnectionProvider - [edfa632a-82, L:/x.x.x.x:50014 ! R:/x.x.x.x:55482] onStateChange(POST{uri/api/platform/tenants/35/rest/channels/14285, connectionPooledConnection{channel[id: 0xedfa632a, L:/x.x.x.x:50014 ! R:/x.x.x.x:55482]}}, [response_incomplete]) 2025-07-25 17:39:11,269 [reactor-http-nio-1] ERROR o.s.b.a.w.r.e.AbstractErrorWebExceptionHandler - [79b8950e-3347] 500 Server Error for HTTP POST /hoss-gateway/api/platform/tenants/35/rest/channels/14285 reactor.netty.http.client.PrematureCloseException: Connection prematurely closed DURING response Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException: Error has been observed at the following site(s): *__checkpoint ⇢ org.springframework.cloud.gateway.filter.WeightCalculatorWebFilter [DefaultWebFilterChain] *__checkpoint ⇢ com.huawei.cbgservice.hoss.apigateway.filter.CorsWebFilter [DefaultWebFilterChain] *__checkpoint ⇢ com.huawei.cbgservice.hoss.apigateway.filter.UrlInterceptorWebFilter [DefaultWebFilterChain] *__checkpoint ⇢ HTTP POST /hoss-gateway/api/platform/tenants/35/rest/channels/14285 [ExceptionHandlingWebHandler] Original Stack Trace:从日志并未看到异常接受到的响应也没看到有啥问题。于是开启服务端微服务的debug日志看看有没有报错信息能够找到一些疑点。2025-07-25 17:39:11,257 [http-nio-8003-exec-9] DEBUG o.a.catalina.valves.RemoteIpValve - Skip RemoteIpValve for request /api/platform/tenants/35/rest/channels/14285 with originalRemoteAddr ‘x.x.x.x’2025-07-25 17:39:11,257 [http-nio-8003-exec-9] DEBUG o.a.c.a.AuthenticatorBase - Security checking request POST /api/platform/tenants/35/rest/channels/142852025-07-25 17:39:11,257 [http-nio-8003-exec-9] DEBUG org.apache.catalina.realm.RealmBase - No applicable constraints defined2025-07-25 17:39:11,257 [http-nio-8003-exec-9] DEBUG o.a.c.a.AuthenticatorBase - Not subject to any constraint2025-07-25 17:39:11,257 [http-nio-8003-exec-9] DEBUG o.a.catalina.core.StandardWrapper - Returning non-STM instance2025-07-25 17:39:11,259 [http-nio-8003-exec-9] DEBUG feign.template.Template - Explicit slash decoding specified, decoding all slashes in uri2025-07-25 17:39:11,260 [http-nio-8003-exec-9] DEBUG feign.template.Template - Explicit slash decoding specified, decoding all slashes in uri2025-07-25 17:39:11,262 [http-nio-8003-exec-9] DEBUG s.n.w.p.http.HttpURLConnection - sun.net.www.MessageHeader42e15a8011 pairs: {POST /v5/tenants/35/channels/14285/options HTTP/1.1: null}{Content-Type: application/json}{token: xx}{Accept:/}{User-Agent: Java/1.8.0_382}{Host: x.x.x.x:51143}{Connection: keep-alive}{Content-Length: 66}2025-07-25 17:39:11,266 [http-nio-8003-exec-9] DEBUG s.n.w.p.http.HttpURLConnection - sun.net.www.MessageHeader3f01bdbc5 pairs: {null: HTTP/1.1 200}{Content-Type: application/json;charsetUTF-8}{Transfer-Encoding: chunked}{Date: Fri, 25 Jul 2025 09:39:11 GMT}{Connection: close}2025-07-25 17:39:11,268 [http-nio-8003-exec-9] DEBUG o.a.coyote.http11.Http11Processor - Socket: [org.apache.tomcat.util.net.NioEndpoint.NioSocketWrapper5ea34be5:org.apache.tomcat.util.net.NioChannel439a4234:java.nio.channels.SocketChannel[connected local/x.x.x.x:8003 remote/x.x.x.x:50014]], Status in: [OPEN_READ], State out: [CLOSED]2025-07-25 17:39:11,268 [http-nio-8003-exec-9] DEBUG o.a.tomcat.util.threads.LimitLatch - Counting down[http-nio-8003-exec-9] latch72025-07-25 17:39:11,268 [http-nio-8003-exec-9] DEBUG o.apache.tomcat.util.net.NioEndpoint - Calling [org.apache.tomcat.util.net.NioEndpoint3951c482].closeSocket([org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper5ea34be5:org.apache.tomcat.util.net.NioChannel439a4234:java.nio.channels.SocketChannel[connected local/x.x.x.x:8003 remote/x.x.x.x:50014]])从服务端的日志也未看到有啥异常因此决定通过tcpdump抓取tcp报文观察连接是否正常关闭。客户端tcpdump内容-已通过访问日志及日志打印的报文进行了精确的匹配服务端tcpdump内容从tcpdum日志来看网络也是正常关闭的。之前有怀疑服务端未正确关闭连接(以前公司内部有人处理过双nginx报类似的错误后面定位是前后nginx对连接的状态判断存在竞争服务端关闭连接时客户端还未感知到并继续发送请求导致报错)因为上面这些证据被排除掉了。其实尝试快速修复的配置也是解决此场景问题的如果是这个问题配置或多或少是能缓解一些的但结果一点都没改善从这两方面都印证此问题跟不正确的连接关闭无关。nginx报错的场景示意图如下第二个nginx关闭连接的报文还未发送到第一个nginx时nginx认为连接还有效因此会继续使用该连接发送请求。对比法确认问题既然系统正确的关闭了连接那只能尝试看看报文是否存在啥问题因此拿报错的和不报错的进行对比看是否有差异。未报错的请求记录的日志2025-07-2517:36:11,015[reactor-http-nio-3]DEBUG r.n.r.DefaultPooledConnectionProvider -[791325c7-41, L:/x.x.x.x:50044 - R:/x.x.x.x:55482]onStateChange(POST{uri/api/platform/tenants/35/rest/channels/14285,connectionPooledConnection{channel[id: 0x791325c7, L:/x.x.x.x:50044 - R:/x.x.x.x:55482]}},[request_sent])2025-07-2517:36:11,039[reactor-http-nio-3]DEBUG reactor.netty.http.client.HttpClient -[791325c7-41, L:/x.x.x.x:50044 - R:/x.x.x.x:55482]READ: 288B -------------------------------------------------|0123456789a b c d e f|-------------------------------------------------------------------------|00000000|485454502f312e3120323030200d 0a63|HTTP/1.1200..c||00000010|6f 6e 6e656374696f 6e 3a206b6565702d|onnection: keep-||00000020|616c6976650d 0a646174653a20467269|alive..date: Fri||00000030|2c203235204a756c2032303235203039|,25Jul202509||00000040|3a33363a313120474d540d 0a 6b656570|:36:11 GMT..keep||00000050|2d616c6976653a2074696d656f75743d|-alive:timeout||00000060|36350d 0a7472616e736665722d656e63|65..transfer-enc||00000070|6f64696e673a206368756e 6b65640d 0a|oding: chunked..||00000080|436f 6e74656e742d547970653a206170|Content-Type: ap||00000090|706c69636174696f 6e 2f 6a736f 6e 3b63|plication/json;c||000000a0|6861727365743d5554462d380d 0a5472|harsetUTF-8..Tr||000000b0|616e736665722d456e636f64696e673a|ansfer-Encoding:||000000c0|206368756e 6b65640d 0a 0d 0a3133310d|chunked....131.||000000d0|0a 7b22737461747573223a224f 4b222c|.{status:OK,||000000e0|226572726f72436f6465223a 6e756c 6c|errorCode:null||000000f0|2c226572726f72446573637269707469|,errorDescripti| |00000100| 6f 6e 22 3a 6e 75 6c 6c 2c 22 65 6e 74 69 74 69 |on:null,entiti| |00000110| 65 73 22 3a 5b 7b 22 6b 65 79 22 3a 22 41 73 79 |es:[{key:Asy| ------------------------------------------------------------------------- 2025-07-25 17:36:11,039 [reactor-http-nio-3] DEBUG r.n.http.client.HttpClientOperations - [791325c7-41, L:/x.x.x.x:50044 - R:/x.x.x.x:55482] Received response (auto-read:false) : RESPONSE(decodeResult: success, version: HTTP/1.1) HTTP/1.1 200 connection: filtered date: filtered keep-alive: filtered transfer-encoding: filtered Content-Type: filtered Transfer-Encoding: filtered 2025-07-25 17:36:11,039 [reactor-http-nio-3] DEBUG r.n.r.DefaultPooledConnectionProvider - [791325c7-41, L:/x.x.x.x:50044 - R:/x.x.x.x:55482] onStateChange(POST{uri/api/platform/tenants/35/rest/channels/14285, connectionPooledConnection{channel[id: 0x791325c7, L:/x.x.x.x:50044 - R:/x.x.x.x:55482]}}, [response_received]) 2025-07-25 17:36:11,039 [reactor-http-nio-3] DEBUG reactor.retry.DefaultRepeat - Stopping repeats since predicate returned false, retry context: iteration1 repeatCompanionValue0 backoff{0ms} 2025-07-25 17:36:11,039 [reactor-http-nio-3] DEBUG reactor.netty.channel.FluxReceive - [791325c7-41, L:/x.x.x.x:50044 - R:/x.x.x.x:55482] [terminatedfalse, cancelledfalse, pending0, errornull]: subscribing inbound receiver 2025-07-25 17:36:11,040 [reactor-http-nio-3] DEBUG reactor.netty.http.client.HttpClient - [791325c7-41, L:/x.x.x.x:50044 - R:/x.x.x.x:55482] READ: 233B ------------------------------------------------- | 0 1 2 3 4 5 6 7 8 9 a b c d e f | ------------------------------------------------------------------------- |00000000| 6e 63 43 68 61 74 55 6e 72 65 73 6f 6c 76 65 64 |ncChatUnresolved| |00000010| 50 72 69 6f 72 69 74 79 4d 69 6e 22 2c 22 76 61 |PriorityMin,va| |00000020| 6c 75 65 22 3a 22 31 32 30 22 7d 2c 7b 22 6b 65 |lue:120},{ke| |00000030| 79 22 3a 22 41 73 79 6e 63 43 68 61 74 45 6e 71 |y:AsyncChatEnq| |00000040| 75 69 72 79 54 69 6d 65 4c 69 6d 69 74 48 6f 75 |uiryTimeLimitHou| |00000050| 72 22 2c 22 76 61 6c 75 65 22 3a 22 34 38 22 7d |r,value:48}||00000060|5d 2c22656e74697479223a 6e756c 6c 2c|],entity:null,||00000070|226669727374223a 6e756c 6c 2c226c61|first:null,la| |00000080| 73 74 22 3a 6e 75 6c 6c 2c 22 73 69 7a 65 22 3a |st:null,size:||00000090|6e756c 6c 2c226e756d626572223a 6e75|null,number:nu||000000a0|6c 6c 2c226e756d6265724f66456c656d|ll,numberOfElem| |000000b0| 65 6e 74 73 22 3a 6e 75 6c 6c 2c 22 74 6f 74 61 |ents:null,tota| |000000c0| 6c 50 61 67 65 73 22 3a 6e 75 6c 6c 2c 22 74 6f |lPages:null,to| |000000d0| 74 61 6c 45 6c 65 6d 65 6e 74 73 22 3a 6e 75 6c |talElements:nul||000000e0|6c 7d 0d 0a300d 0a 0d 0a|l}..0....|-------------------------------------------------------------------------2025-07-2517:36:11,040[reactor-http-nio-3]DEBUG r.n.http.client.HttpClientOperations -[791325c7-41, L:/x.x.x.x:50044 - R:/x.x.x.x:55482]Received last HTTP packet2025-07-2517:36:11,040[reactor-http-nio-3]DEBUG r.n.r.DefaultPooledConnectionProvider -[791325c7, L:/x.x.x.x:50044 - R:/x.x.x.x:55482]onStateChange(POST{uri/api/platform/tenants/35/rest/channels/14285,connectionPooledConnection{channel[id: 0x791325c7, L:/x.x.x.x:50044 - R:/x.x.x.x:55482]}},[response_completed])2025-07-2517:36:11,040[reactor-http-nio-3]DEBUG r.n.r.DefaultPooledConnectionProvider -[791325c7, L:/x.x.x.x:50044 - R:/x.x.x.x:55482]onStateChange(POST{uri/api/platform/tenants/35/rest/channels/14285,connectionPooledConnection{channel[id: 0x791325c7, L:/x.x.x.x:50044 - R:/x.x.x.x:55482]}},[disconnecting])对比后敏锐的发现有问题的请求响应结尾处少了..0....,该部分是Transfer-Encoding:chunked编码格式时的结束报文。初步怀疑tomcat关闭连接时缓存池还未来的及发送的字节流被直接清空了。于是搜索socket相关配置(https://stackoverflow.com/questions/71975992/what-really-is-the-linger-time-that-can-be-set-with-so-linger-on-sockets)看是否有配置与此相关。遂发现connectionLinger配置貌似能够解释的通因此配置上去后确认是否能够解决问题结果还是不行。publicvoidcustomize(TomcatServletWebServerFactoryfactory){factory.addConnectorCustomizers(newTomcatConnectorCustomizer[]{connector-{connector.setProperty(connectionLinger,5);}});}通过日志观察到貌似socket close函数貌似并未阻塞查看tomcat源码后发现socket被配置成非阻塞的那connectionLinger配置就没什么用了。org.apache.tomcat.util.net.NioEndpoint#setSocketOptions// Set socket properties// Disable blocking, polling will be usedsocket.configureBlocking(false);if(getUnixDomainSocketPath()null){socketProperties.setProperties(socket.socket());}至此反思真的是close函数导致数据还没发送就被清空了于是查阅《UNIX网络编程》及使用“可靠的关闭socket”搜索google发现并没有相关资料有对此做说明。所以个人觉得正常使用close函数肯定会保证所有数据都发送完后在开始进行tcp关闭的4次握手不然网络上肯定会有很多相关问题的资料。排除上述问题后继续转头回去确认为啥有问题的请求tomcat没有发送chunked编码的结束报文。接下来的分析方向tomcat发送chunked编码的过程。org.apache.coyote.http11.Http11Processor#prepareResponse通过源码分析得知tomcat是否采用chunked编码并不是由应用层是否添加Transfer-Encoding:chunked头决定的而是是否有传Content-Length头。如果有传Connection: close头即使没传Content-Length头也不会采用chunked编码。从实际结果来看有问题的请求应该走的是逻辑2导致服务端没有发送chunked结束报文。那响应体里面的transfer-encoding:chunked哪里来的同时对比2份响应报文发现无问题的响应有两个Transfer-Encoding:chunked一个大写一个小写有问题的响应只有一个而且是小写的。有问题的无问题的至此我已经基本确认问题所在了,如下代码Controller层直接返回了feign的返回值ResponseEntity里面包含了transfer-encoding:chunked响应头会透传回去但tomcat关闭连接的那次响应并不会使用chunked编码所以api-gateway接受请求时发现响应头里面包含transfer-encoding:chunked因此按chunked编码格式去解码在服务端关闭连接时仍未收到chunked结束报文因此认为未接收到完整的响应而报错。FeignClient()publicinterfacexxFeign{RequestMapping()ResponseEntityApiResponsexxx();}RestControllerpublicclassxxController{privatexxFeign client;RequestMapping()ResponseEntityApiResponseyyy(){returnclient.xxx();}}验证按如下修改后再无报错问题。RestControllerpublicclassxxController{privatexxFeign client;RequestMapping()ResponseEntityApiResponseyyy(){ResponseEntityApiResponseretclient.xxx();returnnewResponseEntity(ret.getBody(),ret.getStatusCode());}}后续分析为什么tomcat在关闭连接时的那次响应不会使用chunked编码tomcat关闭连接后客户端可以通过读取socket返回-1来判定响应是否结束。因此没必要使用chunked编码毕竟chunked编码会增加而外的数据量及解码复杂度。为什么以前使用nginx的时候没有问题这个盲猜是nginx能够处理不标准的http报文有精力的人可以分析一下nginx源码进行印证而spring cloud gateway不行本人也未找到是否有相关配置能够让spring cloud gateway忽略http报文的语法错误而直接透传给前端。针对此问题的补充经过分析及实验上述猜想是错的。实际上如果传了Transfer-Encoding:chunked头http的body又不按照chunked编码来传输nginx也是会报错的。之前之所以不报错是因为nginx只认大写的头而应用层多传的头是小写的读者可以去看上面日志中的http报文。本人是将nginx的源码下载下来然后搜索Transfer-Encoding关键字发现里面用的大写的故猜测之前是因为应用层多余的头采用的是小写nginx不识别还是按照正常报文解析因此没有出问题。所以将系统回退到nginx的组网并且微服务手动返回大写的头然后测试nginx报错截图如上。RequestMapping()ResponseEntityApiResponseyyy(){HttpHeaders headersnewHttpHeaders();ResponseEntityApiResponseretclient.xxx();headers.add(Transfer-Encoding,chunked);returnnew ResponseEntity(ret.getBody(),headers,ret.getStatusCode());}为什么dev环境没有遇到问题也正是dev环境没遇到问题所以该问题流到了现网好在报错的接口对功能没太大影响。dev请求量太低一个连接还没请求到100次就因为等待超时服务端主动关闭了连接另外dev环境开发也经常重启服务也导致一个连接难以请求到100.上述可以通过两方面印证一个是通过请求日志观察是否请求间隔超过60s(tomcat默认超时时间是60s即一个连接60s没有请求则主动关闭连接)另外也可以通过调试会发现连接都是超时关闭而不是请求达到100次(tomcat默认请求100次后关闭连接)后关闭。
RELATED

相关推荐

SAR图像目标识别算法工程实战:PyTorch实现与相位增强

SAR图像目标识别算法工程实战:PyTorch实现与相位增强

简介:这份PDF资料是一篇关于合成孔径雷达图像目标识别的深度学习学术论文,源自长春理工大学学报,适合从事遥感图像解译、SAR目标检测及相关专业研究的学生和工程师参考。文章系统梳理了SAR成像特点与传统识别算法的局限,重点提出基…

📅 2026/9/17 22:33:56
隐形车衣不是越厚越好?临沂车主施工前必读

隐形车衣不是越厚越好?临沂车主施工前必读

很多临沂车主准备贴隐形车衣,容易陷入一个误区:认为隐形车衣厚度越大,产品就越好。实际上,除了厚度,膜品原料、门店施工工艺、技师水平、正品溯源、售后质保,都会直接影响后期使用效果。隐形车衣也就是漆面保护膜,核心作用是保护原厂车漆,抵御石子飞溅磕碰,修复轻微划痕,提升车…

📅 2026/9/17 22:33:56
Xinference 内置视频模型 CogVideoX-2b:text2video 部署与推理实践指南

Xinference 内置视频模型 CogVideoX-2b:text2video 部署与推理实践指南

Xinference 内置视频模型 CogVideoX-2b:text2video 部署与推理实践指南 【免费下载链接】inference Swap GPT for any LLM by changing a single line of code. Xinference lets you run open-source, speech, and multimodal models on cloud, on-prem, or your la…

📅 2026/9/17 22:33:56
MORE NEWS

更多资讯

📰

隔壁开了同品类怎么办?小吃店竞争应对的四个动作

【本篇要点】 先别降价:价格战直接吃利润,而且容易陷入互相压价的死循环。 在顾客能感知的地方拉开差距,比在价格上纠缠更有效。 竞争对手是免费的调研样本,他验证过的做法可以直接借鉴。开小吃店很现实的一件事:你生意…

📰

Wand-Enhancer 本地增强完整指南:一键解锁 Pro 订阅,手机远程面板开箱即用

Wand-Enhancer 本地增强完整指南:一键解锁 Pro 订阅,手机远程面板开箱即用 【免费下载链接】Wand-Enhancer Advanced UX and interoperability extension for Wand (WeMod) app 项目地址: https://gitcode.com/GitHub_Trending/we/Wand-Enhancer …

📰

长沙烧烤培训:素菜与特色串怎么把菜单做厚

【本篇要点】 素菜成本低、出餐快、承担解腻角色,是完全的增量收入。 特色串是摊位招牌,难度更高但一旦做好就是溢价来源。 菜单分三层:基本盘、走量素菜、特色招牌,扩张节奏看经营数据。烧烤的腌料与火候是基本功,这一…

📰

Gutenberg Interactivity API 客户端导航实战:interactivity-router 的区域路由、预取与源码级实现解析

Gutenberg Interactivity API 客户端导航实战:interactivity-router 的区域路由、预取与源码级实现解析 【免费下载链接】gutenberg The Block Editor project for WordPress and beyond. Plugin is available from the official repository. 项目地址: https://g…

📰

2026主流企业邮箱单用户年费收费明细

中小微企业选购企业邮箱,核心参考指标集中在单用户年费、功能权限、存储容量、域名适配四大维度。市面上多数品牌采用打包售卖模式,整体报价容易掩盖单用户真实成本。很多企业采购时,容易出现预算超支、功能冗余或核心功能缺失的问题。本文结…

📰

提示词攻击生成器把 Anthropic 地址改到 TaoToken 后批量生成

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬