HttpClient 4.5 的一些优化

Published on with 0 views and 0 comments

使用单例模式

1.2.1. HttpClient thread safety

HttpClient implementations are expected to be thread safe. It is recommended that the same instance of this class is reused for multiple request executions.

由官方文档可知,HttpClient 是线程安全的,建议使用同一实例。
因此使用单例模式创建,优化反复创建的开销。

设置 Pooling connection manager

PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
// Increase max total connection to 200
cm.setMaxTotal(200);
// Increase default max connection per route to 20
cm.setDefaultMaxPerRoute(20);
// Increase max connections for localhost:80 to 50
HttpHost localhost = new HttpHost("locahost", 80);
cm.setMaxPerRoute(new HttpRoute(localhost), 50);

CloseableHttpClient httpClient = HttpClients.custom()
        .setConnectionManager(cm)
        .build();

设置 keep-alive

是否使用keep-alive要根据业务情况来定
在本业务场景里,我们相当于有少数固定客户端,长时间高频次的访问服务器,启用keep-alive非常合适

自定义一个keep alive strategy

ConnectionKeepAliveStrategy myStrategy = new ConnectionKeepAliveStrategy() {

    public long getKeepAliveDuration(HttpResponse response, HttpContext context) {
        // Honor 'keep-alive' header
        HeaderElementIterator it = new BasicHeaderElementIterator(
                response.headerIterator(HTTP.CONN_KEEP_ALIVE));
        while (it.hasNext()) {
            HeaderElement he = it.nextElement();
            String param = he.getName();
            String value = he.getValue();
            if (value != null && param.equalsIgnoreCase("timeout")) {
                try {
                    return Long.parseLong(value) * 1000;
                } catch(NumberFormatException ignore) {
                }
            }
        }
        HttpHost target = (HttpHost) context.getAttribute(
                HttpClientContext.HTTP_TARGET_HOST);
        if ("www.naughty-server.com".equalsIgnoreCase(target.getHostName())) {
            // Keep alive for 5 seconds only
            return 5 * 1000;
        } else {
            // otherwise keep alive for 30 seconds
            return 30 * 1000;
        }
    }

};

CloseableHttpClient client = HttpClients.custom()
        .setKeepAliveStrategy(myStrategy)
        .build();

设置 Connection eviction policy

manager为 Pooling connection manager

        // 开启监控线程,对异常和空闲线程进行关闭
        ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1);
        executorService.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                // 关闭异常连接
                manager.closeExpiredConnections();
                // 关闭30s空闲的连接
                manager.closeIdleConnections(30, TimeUnit.MILLISECONDS);
//                log.info("close expired and idle for over 30s connection");
            }
        }, 30, 5, TimeUnit.SECONDS);