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