1、写了一个httpclient的工具类,也写了重试的逻辑,
但是在多个线程在使用同一个httpclient实例的时候,
发现线程read time out的超时并没有被重发很郁闷(线程直接进入的SocketTimeoutException异常,
导致本次线程的请求没有拿到再次重发后的结果,导致数据丢失)
public CloseableHttpClient getHttpClient() {
return HttpClients.custom().
setConnectionManager(connMrg).
setKeepAliveStrategy(myStrategy).
setDefaultRequestConfig(requestConfig).
setConnectionManagerShared(true).
setMaxConnTotal(maxTotal).
setRetryHandler(
new HttpRequestRetryHandler() {
@Override
public boolean retryRequest(IOException exception , int executionCount , HttpContext context) {
// 重试3次,从3开始
if (executionCount > 3) {
return false;
}
/*
if (exception instanceof NoHttpResponseException) {
System.out.println(
"[NoHttpResponseException has retry request:" + context.toString() + "][executionCount:" + executionCount + "]");
return true;
}
else if (exception instanceof SocketException || exception instanceof ConnectTimeoutException || exception instanceof SocketTimeoutException ) {
System.out.println("[SocketException has retry request:" + context.toString() + "][executionCount:" + executionCount + "]");
return true;
}
*/
if (exception instanceof UnknownHostException) {
return false;
}
// SSL handshake exception
if (exception instanceof SSLException) {
return false;
}
//除上述两种异常其他异常均重试3次,其实主要问题在于
//服务端对连接数限制,会导致你再怎么重试,都会异常,连接数满了,重试还有毛用
//所以设置连接池的时候需要设置的比他们的最大值小,用完要及时释放到连接池
String time3 = new SimpleDateFormat("HH:mm:ss.SSS").format(new Date());
System.out.println("time:"+time3+"="+Thread.currentThread().getName() +"\n"+"[Exception:"+exception.toString()+" has retry request:" + context.toString() + "][executionCount:" + executionCount + "]");
return true;
}
}
).
build();
}
问题3: String time3 = new SimpleDateFormat("HH:mm:ss.SSS").format(new Date());
System.out.println("time:"+time3+"="+Thread.currentThread().getName() +"\n"+"[Exception:"+exception.toString()+" has retry request:" + context.toString() + "][executionCount:" + executionCount + "]");
return true;
这段代码发生read time out的时候执行了,但是executionCount一直都是1,我理解应该是重发了一次,但是子线程里的日志打印了异常,并没有获取到重试后的结果
问题4,子线程取数据逻辑,只写了主要逻辑
httpPost.setHeader("Content-Type", "text/xml;charset=UTF-8");
// httpPost.setHeader("SOAPAction", "");
StringEntity data = new StringEntity(inputPara, Charset.forName("UTF-8"));
httpPost.setEntity(data);
try {
response = httpClient.execute(httpPost);
httpEntity = response.getEntity();
if (httpEntity != null) {
// 获取响应内容
returnVal = EntityUtils.toString(httpEntity, "UTF-8");
// 消费掉节约内存,并关闭inputstream流
EntityUtils.consume(httpEntity);
}
} catch (Exception e) {
e.printStackTrace();
}
finally {
try {
// 关闭流并释放资源
response.close();
} catch (Exception e) {
e.printStackTrace();
}
}
我认为在这段的httpEntity = response.getEntity();执行的时候
readtime out,然后代码直接进入了catch逻辑,所以重发后的结果并没有取到。
问题5:
1、我就是想解决,读取超时就重发,一直到3次结束。
2、是不是我设置的读取超时时间为60s导致根本没办法重发,服务端可能已经把短连接关闭了
因为http默认短连接时间好像就是60s。我猜测,如果我设置读取时间为10s,可能就可以重试3次了。
3、
try{
httpEntity = response.getEntity();
}
catch()
{
}
这段逻辑跟
创建httpclient的方法里面的重试方法,当发生异常时,到底是这段阻塞httpEntity = response.getEntity(); 等待3次重发?还是是异步的,里面重发,外面直接进入异常逻辑,根本不等重发后的结果