先了解一下 java.io.IOException: Broken pipe
pipe是管道的意思,管道里面是数据流,通常是从文件或网络套接字读取的数据。 当该管道从另一端突然关闭时,会发生数据突然中断,即是broken
场景:我们平台(简称A)调用其他小组平台(简称B平台)
调用方式:httpclient post请求
问题:A调用B平台接口,B平台接口正常执行,但是返回结果很忽快忽慢(可能是他们接口原因),慢的时候可能***10分钟***都没有响应时间。
导致结果:在并发量大的情况下A平台的该接口因为长期没收到返回结果,然后还不断的有请求进来,会导致线程阻塞,就会报java.io.IOException: Broken pipe,最后还会有可能影响项目中其他接口的速度,
下面是我们的报错日志
user/getUserDaBiaoScore该接口调用B平台接口响应慢报错
请求方式:[GET]
请求路径:[user/getUserDaBiaoScore]
请求参数:[]
异常信息:[java.io.IOException: Broken pipe]
login/loginOut 该接口为退出接口,应该是受上面的接口影响导致报错
请求方式:[GET]
请求路径:[/login/loginOut]
请求参数:[]
异常信息:[java.io.IOException: Broken pipe]
解决思路:设置一个时间,当B平台接口多少秒内没有返回结果就直接抛弃此次请求(因为这个接口对我们来说不是很重要,只是一个显示用户达标数据)。
一开始想着设置一个全局超时时间,但是由于我们项目中一些接口的响应时间不一样(部分业务比较复杂,返回数据比较多),所以这个方法肯定不可行。
因为我们调用B平台是通过http方式调用,所以可以在http调用的方法做手脚。
设置一下超时时间,下面是代码
public static String post(String url, Map < String, Object > paramsMap) {
CloseableHttpClient client = HttpClients.createDefault();
String responseText = "";
CloseableHttpResponse response = null;
try {
HttpPost method = new HttpPost(url);
RequestConfig requestConfig = RequestConfig.custom()
.setConnectTimeout(10000).setConnectionRequestTimeout(10000)
.setSocketTimeout(10000).build();
//设置超时时间
//setConnectTimeout:设置连接超时时间,单位毫秒。
//setConnectionRequestTimeout设置从connect Manager获取Connection 超时时间,单位毫秒。
//请求获取数据的超时时间,单位毫秒。 如果访问一个接口,多少时间内无法返回数据,就直接放弃此次调用。
method.setConfig(requestConfig);
if (paramsMap != null) {
ArrayList<NameValuePair> paramList = new ArrayList <NameValuePair> ();
for (Map.Entry < String, Object > param: paramsMap.entrySet()) {
NameValuePair pair=new BasicNameValuePair(param.getKey(),param.getValue().toString());
paramList.add(pair);
}
method.setEntity(new UrlEncodedFormEntity(paramList,"UTF-8"));
}
response = client.execute(method);
HttpEntity entity = response.getEntity();
if (entity != null) {
responseText = EntityUtils.toString(entity, "UTF-8");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
response.close();
} catch (Exception e) {
System.out.println("请求超过10s,抛弃此次请求");
e.printStackTrace();
}
}
return responseText;
}
我用的httpclient版本是4.5.2。每个版本的设置时间好像不太一样,这里就不再一一说明了。