Bootstrap

org.apache.http.ConnectionClosedException Premature end of Content-Length delimited message body

最近生产环境报了这个系统异常:

org.apache.http.ConnectionClosedException Premature end of Content-Length delimited message body (expected 107915; received 40177)

查看日志后发现是下载文件的时候出错。

具体的代码如下:

StringEntity entityParams = new StringEntity(requestXml, "utf-8");
			HttpPost httpPost = new HttpPost(serverUrl);
			httpPost.setEntity(entityParams);
			httpPost.setHeader("Content-Type", "text/xml;charset=ISO-8859-1");
			client = HttpClients.createDefault();
			// 向威富通发送对账请求,并获取结果
			response = client.execute(httpPost);

在向威富通发送请求的时候有下载文件的操作,出现了该问题。

起初是怀疑http的超时时间过短导致了该问题,由于默认的时间是30s,并且我们接收到的没有到总的1/2(4w/10w),所以将超时时间设置为了120s,修改后的代码如下:

StringEntity entityParams = new StringEntity(requestXml, "utf-8");
			HttpPost httpPost = new HttpPost(serverUrl);
			RequestConfig config = RequestConfig.custom().setSocketTimeout(120000).setConnectTimeout(120000).build();
			httpPost.setConfig(config);
			httpPost.setEntity(entityParams);
			httpPost.setHeader("Content-Type", "text/xml;charset=ISO-8859-1");
			client = HttpClients.createDefault();
			// 向威富通发送对账请求,并获取结果
			response = client.execute(httpPost);

但是在重新执行该代码的时候还是报同样的问题,修改tomcat和nginx的超时时间都没有解决该问题。另外有一些细节需要注意:

1.多次下载同一个文件时的received都是40177。

2.第二天的文件更大,达到了15w,此时的received仍然是40177。

所以有很大的理由来怀疑是Nginx的缓冲区大小导致了该问题。

在Nginx的配置文件中(http内server外)加入以下代码:

sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    #gzip  on;
    
    #以上为系统自带 以下为自己添加
    proxy_buffering on;
    proxy_buffer_size 64k;
    proxy_buffers 8 32k;
    proxy_temp_path proxy_temp 1 2;
    proxy_request_buffreing on;
    proxy_read_timeout 300s;
    proxy_send_timout 300s;

然后重新执行这段代码得以解决该问题。

参考文章:记一个 httpclient 神坑 - 掘金 (juejin.cn)