问题概述
测试同学请求某接口,偶尔会出现一个错误提示。此接口在 body 中会传一段 base64 后的 json。看服务端的日志发现有异常日志,如下图。具体打印出 body ,发现拿到的是截断的字符串。
排查问题
- 正好测试有抓到app的异常的包,当我们查看此包时,发现包中 body 无问题。排除前端问题。
- 直接在业务服务器端抓包,看传递过来的参数是否有问题。于是通过 charles repeat 功能,重复请求接口以复现问题。
同时在业务服务器端 tcpdump -i any port 8080 -A -s 1500 。复现后。查看同一个 traceId 的包。发现确实有问题。body 的数据分成了两个 tcp 包。而我们在代码中 debug 拿到的数据确实只有前面这一段。(图中取的是不同的包,可不必在意数据不一样)
为了更好的看清包是否都正常。直接通过 tcpdump -i any port 8080 -A -s 1500 -w test.cap 。重新 repeat 请求然后导入到 wireshark 中方便查看。
- 这里看起来包都正常,那么就把问题定位到代码层面去分析了。关键代码如下。我们发现这时 available 方法返回的数值只有一部分。
这个 avaiable()方法 获取到的值是不是有问题,后来 google 发现这个方法调用时,数据可能还没完全读入。于是改写了方法。先读出 content-length 。再通过循环等待,调用 avaiable() 方法。期待能获取完整的数据。可惜并没有用。
4.于是去查看,工具类中是否有类似方法。于是查看了 FormHttpMessageConverter 中读取 body。
5.改写为直接调用 StreamUtils 工具类。测试后无问题。
这里顺便说下,debug available() 方法,看到的注释。这个数值不一定准确,不要依赖他。
另外
还有两个问题需要再去分析一下。
- 前端的包会先到一个 【网关服务】 ,再由【网关服务】转发到【业务服务】。网关服务收到包时是1个完整的包。而转发到业务服务变成了多个包。虽然增加了一些头部,但看长度并未达到拆包的程度。需要再去查下原因网关服务做了什么特殊处理。
- 没有完全debug到 available() 方法是为何没有把第二个 tcp 包body 长度计算进去的?只是从注释上分析。