一次现网问题定位-com.google.gson.JsonSyntaxExceptio on: java.io.EOFException: End of input 背景收到隔壁组请求支援定位调用接口报错报错日志如下2026-08-28 16:07:22.462 [http-nio-8003-exec-14] ERROR [UnknownExceptionHandler:28]com.google.gson.JsonSyntaxException on: java.io.EOFException: End of input at line 1 column 1479 path $.notification[5].lastUpdateDateat com.google.gson.Gson.fromJson(Gson.java:1370)at com.google.gson.Gson.fromJson(Gson.java:1262)at com.google.gson.Gson.fromJson(Gson.java:1171)at com.google.gson.Gson.fromJson(Gson.java:1107)…从报错日志初步来看像是json不完整解析过程中碰到结束符了。他们提供了代码从代码逻辑看非常简单他们先通过RestTemplate转成String然后在手工序列化。报错就发生在序列化那一行。StringresponserestTemplate.doGet(url,headers,String.class);TkbHotResponsetkbHotResponseGSON.fromJson(response,TkbHotResponse.class);系统组网如下日志告警的系统ALB上游系统定位思路先定界-是不是json不完整从报错来看像是json不完整首先得把这个方向确认了才好继续往下定位因此通过堆栈稍微看了下Gson的源码确认后着手定位为什么输入的字符串不是完整的json。初步想法是不是上游因为啥原因导致传输的json就不完整。隔壁组提供了使用postman调用的响应里面内容是完整的。该场景排除。为什么restTemplate返回的String不是完整的json通过上一步的分析上游传的数据是没问题的那初步认为是不是偶发网络提前中断了导致数据没传输完如果是上述场景的话那按说RestTemplate会抛异常吧看了前后日志并没有异常难道RestTemplate接受到200的响应如果读取响应过程中连接中断不会有异常遂初步翻翻RestTemplate的源码看看反序列化网络字节流转String的过程是怎么样的。protectedStringreadInternal(Class?extendsStringclazz,HttpInputMessageinputMessage)throwsIOException{CharsetcharsetgetContentTypeCharset(inputMessage.getHeaders().getContentType());longlengthinputMessage.getHeaders().getContentLength();byte[]bytes(length0lengthInteger.MAX_VALUE?inputMessage.getBody().readNBytes((int)length):inputMessage.getBody().readAllBytes());returnnewString(bytes,charset);}通过阅读StringHttpMessageConverter代码发现以下可疑点如果传来Content-Length头会根据这个头的长度来读取响应。我感觉像是传了错误的Content-Length头因为如果是网络问题报错概率应该很小但是我看日志还挺多的。为此我找他们用postman调用了一下看看是不是有传这个头。结果还真有从他们上面截图可以看到除了传Content-Length头还传了Content-Encoding:gzip。我感觉应该是启用了压缩然后Content-Length头传的是压缩后的值。如果像猜想一样的话那这个问题应该是必现找隔壁项目组求证后得到了肯定的答复。为此坚定了这个定位方向。接下来就是找上游确认Content-Length是怎么写进去的压缩到底是谁做的。和上游定位Content-Length是怎么传的里面的值怎么来的先是找他们确认Content-Length头是他们传的还是ALB传的通过访问了单边地址防止ALB的干扰发现这个头确实是他们自己传的。然后就联合上游分析他们代码咋写的这头是他们自己代码写的还是tomcat写的通过分析代码发现确实是他们自己写的这个头。publicvoiddoWrite(byte[]content,HttpServletResponsehttpResponse)throwsIOException{httpResponse.setContentType(text/html; charsetUTF-8);httpResponse.addHeader(Content-Length,Integer.toString(content.length));httpResponse.addHeader(Content-Encoding,gzip);StreamUtil.transfer(newBufferedInputStream(newByteArrayInputStream(content)),httpResponse.getOutputStream());}# doWrite中的content参数从pullHtml函数中获取publicbyte[]pullHtml(HttpServletRequestrequest,HttpServletResponseresponse,WebRequestVOwebRequest,XhtmBeanxhtmBean)throwsIOException{returntoGzipByteArray(createHtml(request,response,webRequest,xhtmBean),UTF_8);}从他们代码中得到一下信息他们会自己对数据做压缩压缩完后同时传了Content-Length和gzip的压缩头。所以Content-Length头的值是没问题的代表的是HTTP响应中body的真实字节数。至此问题根因初步明确了RestTemplate拿到的Content-Length的值是压缩后的导致反序列化时字节数读少了。接下来的问题就是为什么测试环境没这个问题而生产有这个问题。生产和测试的差异通过对比生产和测试环境的响应发现响应头有些差异测试环境没有Content-Length头变成了Transfer-Encoding:chunked生产环境测试环境Content-Length: 1542Transfer-Encoding:chunkedContent-Encoding:gzipContent-Encoding:gzip从结果来看像是生产环境ALB完全透传后台的数据而测试环境像是先解压然后重新压缩这样有Transfer-Encoding:chunked。为了确认是ALB的问题我们绕过ALB调用了单边地址直接调用微服务发现测试/生产都一样返回的头与代码逻辑一致包含Content-Length和Content-Encoding:gzip。以上得出结论相同响应经过不同环境的ALB后产生了差异。ALB其实也就是ningx在找他们之前自己也做了功课搜了一下nginx什么情况下会解压后端数据后重新压缩AI告知场景一Nginx 开启了内容替换或修改模块最常见如果你在 Nginx 中配置了对网页内容的实时修改例如修改域名、注入脚本、替换文本Nginx 必须拿到明文内容才能进行字符串匹配和替换。我们并看不到ALB的配置因此找他们求证得到的答复是我们测试环境的网页上面会显示BETA的样式这个是他们拦截了请求并注入了特定的内容而生产没有到此疑问得以消除AI的答案还是很有参考性的。目前还剩最后一个疑问为什么之前没有而现在才有双方都检查一下包上游没有任何修改而隔壁组最近升级了开源软件。HttpClient5由5.5升级到5.6.x了通过调试发现在内容压缩的情况下两者对Content-Length头的处理由差异前者会吞掉它而后者原封不动的给调用方因此RestTemplate拿到了错误的值。此致所有疑问得以解决。小插曲实际上前面我并不知道上游应用自己做了压缩没看到对应代码为此我还看了tomcat的源码看应用层传Content-Encoding:gzip头tomcat会做何处理tomcat何种情况下会进行压缩压缩后会不会覆盖应用层写的Content-Length。毕竟初步看他们代码时没看仔细没发现他们自己有做压缩。既然他们应用层传的值没问题那很有可能是tomcat进行了压缩并覆盖了该值。通过源码确认以下事实tomcat靠全局配置启用压缩应用层传了Content-Encoding:gzip头后tomcat认为应用层已经压缩过了就算tomcat启用了压缩也不会再次做压缩。经此分析后出现了矛盾的地方应用层传了正确的值tomcat又不做压缩那为什么通过访问单边地址看到的Content-Length头的值不正确为此和他们一起仔细调试了代码然后就发现他们自己代码做了压缩该值是压缩后的值。

相关新闻

最新新闻

iQOO Z11 Turbo与Z12 Turbo怎么选?二手淘机验机避坑指南

iQOO Z11 Turbo与Z12 Turbo怎么选?二手淘机验机避坑指南

这次我们来看一个二手机圈最近讨论度不低的换机话题:iQOO Z11 Turbo 和 iQOO Z12 Turbo,到底该等新机,还是去二手市场掏一台性价比更高的旧款。标题里的“拍机堂淘机”“淘机认准极光”已经说明,这大概率不是在聊官方发布会&#…

2026/9/1 16:52:12
电台老鼠与MPX清图:SDR调频接收链路优化指南

电台老鼠与MPX清图:SDR调频接收链路优化指南

先把话说在前面:如果你也听别人反复提到“电台老鼠”“MPX”“清图”这几个词,又找不到一篇能讲清楚的说明,那这篇文章就是给你的。我在折腾调频广播接收时,最常看到的一个场景是——有人用很便宜的 USB 式 SDR 接收器听广播&…

2026/9/1 16:52:12
滑动窗口注意力下的KV缓存:为什么必须用环形缓存?

滑动窗口注意力下的KV缓存:为什么必须用环形缓存?

滑动窗口注意力在模型推理中经常和 KV 缓存一起出现。很多人第一次接触这个概念时,会先想到注意力矩阵从 N x N 变成 N x W,于是认为计算量变小了。但真正影响长上下文部署的往往不是那一次矩阵乘,而是 Key 和 Value 缓存的存放方式。这里要回…

2026/9/1 16:52:12
解决macOS定时任务失效:构建菜单栏守护进程确保cron准时执行

解决macOS定时任务失效:构建菜单栏守护进程确保cron准时执行

在 macOS 上,定时任务(cron)是一个经典但有时会“失灵”的工具。许多开发者都遇到过这样的场景:精心配置了一个crontab,期望它在凌晨执行数据备份、日志清理或 API 同步,结果第二天检查时发现任务根本没有运…

2026/9/1 16:52:12
基于SpringBoot的车辆维修保养系统的设计与实现(源码+文档+部署讲解等)

基于SpringBoot的车辆维修保养系统的设计与实现(源码+文档+部署讲解等)

联系博主 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 …

2026/9/1 16:52:12
【智能制造】2026零碳工厂建设方案【附全文阅读】

【智能制造】2026零碳工厂建设方案【附全文阅读】

本方案面向制造企业高管、EHS 与能源管理负责人、双碳咨询从业者,以光伏行业为样本,指导工业企业零碳工厂落地建设。文档立足国内双碳目标,剖析工业领域减排紧迫性,围绕范围一、二、三全维度碳排放,输出清洁能源替代、…

2026/9/1 16:47:12