我正在访问一个返回大约 900k XML 的端点。我时不时地(在今天的测试中不到 5000 分之一)我得到一个 MalformedChunkCodingException
这是从一个相当老的 web 应用程序(约 10 年)发生的,它基于 Spring 3 构建。我转而使用 RestTemplate 而不是直接使用 httpclient,但这并没有解决它。今天在 httpclient 上启用了线级日志记录的情况下运行了几个小时后,我设法捕获了一个。
Caused by: org.apache.http.MalformedChunkCodingException: Unexpected content at the end of chunk
at org.apache.http.impl.io.ChunkedInputStream.getChunkSize(ChunkedInputStream.java:259)
at org.apache.http.impl.io.ChunkedInputStream.nextChunk(ChunkedInputStream.java:227)
at org.apache.http.impl.io.ChunkedInputStream.read(ChunkedInputStream.java:186)
at org.apache.http.conn.EofSensorInputStream.read(EofSensorInputStream.java:137)
at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
at java.io.InputStreamReader.read(InputStreamReader.java:184)
at java.io.Reader.read(Reader.java:140)
at org.springframework.util.StreamUtils.copyToString(StreamUtils.java:74)
at org.springframework.http.converter.StringHttpMessageConverter.readInternal(StringHttpMessageConverter.java:85)
at org.springframework.http.converter.StringHttpMessageConverter.readInternal(StringHttpMessageConverter.java:40)
at org.springframework.http.converter.AbstractHttpMessageConverter.read(AbstractHttpMessageConverter.java:153)
at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:103)
at org.springframework.web.client.RestTemplate$ResponseEntityResponseExtractor.extractData(RestTemplate.java:724)
at org.springframework.web.client.RestTemplate$ResponseEntityResponseExtractor.extractData(RestTemplate.java:709)
通常日志似乎是这样的:
DEBUG org.apache.http.wire - << "words words words"
DEBUG org.apache.http.wire - << "[\r][\n]"
DEBUG org.apache.http.wire - << "FAF[\r][\n]"
DEBUG org.apache.http.wire - << "words words words up to FAF bytes"
DEBUG org.apache.http.wire - << "[\r][\n]"
DEBUG org.apache.http.wire - << "BAA[\r][\n]"
DEBUG org.apache.http.wire - << "words words words up to BAA bytes"
但是在那个出错的地方我有这个:
DEBUG org.apache.http.wire - << "words words words"
DEBUG org.apache.http.wire - << "[\r][\n]"
DEBUG org.apache.http.wire - << "B50[\r][\n]"
DEBUG org.apache.http.wire - << "words words words up to B50 bytes"
DEBUG org.apache.http.wire - << "3FC0[\r][\n]"
它缺少 B50 block 末尾的 [\r][\n]。
所以,假设我可以信任 org.apache.http.wire 调试,那么我的应用程序正在接收这样的流,而且它的格式是错误的。它们之间的 haproxy 是否有可能破坏流?
幸运与否,对话的另一端也是我的一个应用程序,运行在 tomcat 和 Spring 4.2.4 中。
我从哪里开始寻找谁在构建无效响应? Spring ? Tomcat ?
看起来我可以禁用分块,但只能在构建响应时计算我的内容长度,我不太愿意这样做,因为那样我就必须手动序列化我的响应,而不是让 Spring做吧。
最佳答案
正如您所说,该应用程序很旧。您可能需要更新所有库版本,希望该问题已在某处检测到并修复。
但是找到不良行为者会有所帮助,因为您只需要修复那个。
根据我自己在 HTTP 工具中测试错误语法支持的经验,我很确定 Haproxy 是您列出的元素中更强大的元素。但这并不排除那里的问题。
发送端点和接收端点之间的每个 HTTP actor 都可以更改 HTTP 主体(修改 block 大小),因此您需要捕获所有 actor(spring、tomcat、haproxy、任何其他代理和/或反向)的输入和输出代理、负载均衡器、ssl 终结器)来检测坏 block 。我将从消息发射器、XML 端点开始。我会使用 wireshark/pcap/httpdump,这是真正捕获 TCP 和 HTTP 流量的东西。但是您可能必须找到一种方法来快速丢弃捕获,直到您到达失败点,因为 1/5000 意味着您有捕获大量数据的巨大风险。
关于java - block 末尾的意外内容 - 是什么构建了损坏的流?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57732129/