虽然现在基于netty和thift的微服务非常的流行,但是公司内部的蛮多系统仍然对外提供http接口。在调用http接口工具类中,apache httpclient工具用的比较多。下面列举一些正确使用httpclient的一些要点。
设置socketTimeout
可以在RequestConfig
中设置socketTimeout,表示数据传输处理时间,如下:
RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(4000).build()
设置connectionRequestTimeout
可以在RequestConfig
中设置socketTimeout,表示从连接池中后去连接的timeout时间,如下:
RequestConfig requestConfig = RequestConfig.custom().setConnectionRequestTimeout(1000)
设置connectTimeout
可以在RequestConfig
中设置connectTimeout,表示建立连接的timeout时间,如下:
RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(3000).build()
设置MaxTotal
MaxTotal表示连接池最大并发连接数,代码如下:
PoolingHttpClientConnectionManager pccm = new PoolingHttpClientConnectionManager(); pccm.setMaxTotal(300);
设置DefaultMaxPerRout
DefaultMaxPerRout表示单路由的最大并发连接数,假设你的业务系统需要调用A和B这两个外部系统的http接口,那么如果DefaultMaxPerRout=100,那么调用A系统的http接口时,最大并发数就是100。代码如下:
PoolingHttpClientConnectionManager pccm = new PoolingHttpClientConnectionManager(); pccm.setDefaultMaxPerRoute(100);
尽量不要设置超时重试次数
如果要设置的话,可以如下设置:
RequestConfig params = RequestConfig.custom().setConnectTimeout(3000).setConnectionRequestTimeout(1000).setSocketTimeout(4000) .setExpectContinueEnabled(true).build(); PoolingHttpClientConnectionManager pccm = new PoolingHttpClientConnectionManager(); pccm.setMaxTotal(300); pccm.setDefaultMaxPerRoute(50); HttpRequestRetryHandler retryHandler = new HttpRequestRetryHandler() { public boolean retryRequest(IOException exception , int executionCount , HttpContext context) { if (executionCount > 3) { return false; } if (exception instanceof NoHttpResponseException) { LOGGER.info( "[NoHttpResponseException has retry request:" + context.toString() + "][executionCount:" + executionCount + "]"); return true; } else if (exception instanceof SocketException) { LOGGER.info("[SocketException has retry request:" + context.toString() + "][executionCount:" + executionCount + "]"); return true; } return false; } }; httpclient = HttpClients.custom().setConnectionManager(pccm).setDefaultRequestConfig(params).setRetryHandler(retryHandler) .build();
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
完整代码
package testimport java.io.IOExceptionimport java.io.UnsupportedEncodingExceptionimport java.net.SocketExceptionimport java.util.ArrayListimport java.util.Listimport java.util.Mapimport java.util.Map.Entryimport org.apache.http.HttpEntityimport org.apache.http.HttpStatusimport org.apache.http.NameValuePairimport org.apache.http.NoHttpResponseExceptionimport org.apache.http.client.HttpRequestRetryHandlerimport org.apache.http.client.config.RequestConfigimport org.apache.http.client.entity.UrlEncodedFormEntityimport org.apache.http.client.methods.CloseableHttpResponseimport org.apache.http.client.methods.HttpPostimport org.apache.http.client.methods.HttpUriRequestimport org.apache.http.impl.client.CloseableHttpClientimport org.apache.http.impl.client.HttpClientsimport org.apache.http.impl.conn.PoolingHttpClientConnectionManagerimport org.apache.http.message.BasicNameValuePairimport org.apache.http.protocol.HttpContextimport org.apache.http.util.EntityUtilsimport org.slf4j.Loggerimport org.slf4j.LoggerFactoryimport com.alibaba.fastjson.JSONpublic class HttpClientUtils { private final static Logger LOGGER = LoggerFactory.getLogger(HttpClientUtils.class) private final static String UTF8 = "UTF-8" public static CloseableHttpClient httpclient = null static { // 初始化线程池 RequestConfig params = RequestConfig.custom().setConnectTimeout(3000).setConnectionRequestTimeout(1000).setSocketTimeout(4000) .setExpectContinueEnabled(true).build() PoolingHttpClientConnectionManager pccm = new PoolingHttpClientConnectionManager() pccm.setMaxTotal(300) pccm.setDefaultMaxPerRoute(50) HttpRequestRetryHandler retryHandler = new HttpRequestRetryHandler() { public boolean retryRequest(IOException exception , int executionCount , HttpContext context) { // 重试1次,从1开始 if (executionCount > 1) { return false } if (exception instanceof NoHttpResponseException) { LOGGER.info( "[NoHttpResponseException has retry request:" + context.toString() + "][executionCount:" + executionCount + "]") return true } else if (exception instanceof SocketException) { LOGGER.info("[SocketException has retry request:" + context.toString() + "][executionCount:" + executionCount + "]") return true } return false } } httpclient = HttpClients.custom().setConnectionManager(pccm).setDefaultRequestConfig(params).setRetryHandler(retryHandler) .build() } public static String post(String urlToRequest , Map<String, Object> parameters , Integer connectionRequestTimeout , Integer connectTimeout , Integer socketTimeout) { Long startTs = System.currentTimeMillis() List<NameValuePair> nvps = new ArrayList<NameValuePair>() if (parameters != null && !parameters.isEmpty()) { for (Entry<String, Object> entry : parameters.entrySet()) { nvps.add(new BasicNameValuePair(entry.getKey(), String.valueOf(entry.getValue()))) } } try { LOGGER.info("post-req:url:{},param:{}", urlToRequest, JSON.toJSONString(parameters)) HttpPost post = new HttpPost(urlToRequest) if (connectionRequestTimeout != null && connectTimeout != null && socketTimeout != null) { RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(connectTimeout) .setConnectionRequestTimeout(connectionRequestTimeout).setSocketTimeout(socketTimeout).build() post.setConfig(requestConfig) } post.setEntity(new UrlEncodedFormEntity(nvps, UTF8)) String result = invoke(post) Long endTs = System.currentTimeMillis() Long currentMethodCallTime = endTs - startTs if (currentMethodCallTime > 5000) { LOGGER.warn("url:{},call time {} ms", urlToRequest, currentMethodCallTime) LOGGER.info("所有存活线程="+Thread.getAllStackTraces().size()) } LOGGER.info("post-rps:{}", result) return result } catch (UnsupportedEncodingException e) { LOGGER.error("[HttpClientUtils][post][Unsupported Encoding Exception]", e) } return null } private static String invoke(HttpUriRequest request) { CloseableHttpResponse response = null try { response = httpclient.execute(request) if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) { HttpEntity entity = response.getEntity() return EntityUtils.toString(entity, UTF8) } } catch (IOException e) { LOGGER.error( "[HttpClientUtils][invoke][method:" + request.getMethod() + " URI:" + request.getURI() + "] is request exception", e) } finally { if (response != null) { try { response.close() } catch (IOException e) { LOGGER.error( "[HttpClientUtils][invoke][method:" + request.getMethod() + " URI:" + request.getURI() + "] is closed exception", e) } } } return null }}
0 0