客户端上传文件发生Connection reset by peer: socket write error问题排查

1.问题描述

研发在测试环境进行测试,通过内网上传文件能正常收到nginx返回的错误信息,nginx做了30MB大小的上传限制

{
    "return_code": 20010,
    "returnDesc": "Request body too large. It should not exceed [30 MB]"
}

通过走公网域名访问应用程序就会报错:

java.net.SocketException: Connection reset by peer: socket write error

2.问题排查

首先在客户端抓包发现服务器在tcp连接中返回了RST包

客户端上传文件发生Connection reset by peer: socket write error问题排查_第1张图片

由于nginx服务器做了上传文件大小限制,那么推测上传文件太大超过了nginx的限制,于是nginx返回了文件太大的报错,但此时应用程序仍然在发送数据流,因此nginx发现自己的响应没有得到回馈,于是返回了RST包。如果此时客户端正在往Socket套接字的输入流中写数据则会提示“Connection reset by peer”。

那为什么内网测试能收到正常返回的数据呢?收到正常返回数据说明client正常完成了一次请求,由于内网速度远远大于外网速度,文件又不是足够的大,因此client在发送完数据流后正常响应了nginx的response。

3.一波三折

又有同事反馈说,通过postman以同样的外网环境调用接口上传文件时,postman能正常接收到返回的数据

客户端上传文件发生Connection reset by peer: socket write error问题排查_第2张图片

同样的环境,为啥客户端去访问却报错,postman能正常接收到数据呢,难道postman有什么异常处理机制?抓包发现通过postman去调用接口的时候链接并没有被RST,而是正常关闭的,并且并没有发生文件的上传

客户端上传文件发生Connection reset by peer: socket write error问题排查_第3张图片

4.问题解决

在网上查询了半天,发现http协议中有这么一个header:Expect:100-continue:

客户端上传文件发生Connection reset by peer: socket write error问题排查_第4张图片

尝试在代码中加入这个header,问题得以解决:

客户端上传文件发生Connection reset by peer: socket write error问题排查_第5张图片

你可能感兴趣的:(网络,linux,http)