关于httpClient 使用的注意事项

关于httpClient 使用的注意事项

用例
        PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
        // 最大连接数-不设置默认20
        connectionManager.setMaxTotal(200);
        // 每个路由最大连接数-不设置默认2
        connectionManager.setDefaultMaxPerRoute(100);
        CloseableHttpClient httpClient = HttpClients.custom().setDefaultRequestConfig(
                        RequestConfig.custom()
                                // 连接服务器(握手)的超时时间
                                .setConnectTimeout(3000)
                                // 被请求服务器响应(response)的超时时间
                                .setSocketTimeout(5000)
                                // 从连接池中获取连接的超时时间
                                .setConnectionRequestTimeout(3000)
                                .build()
                ).setConnectionManager(connectionManager)
                .build();
三个连接超时时间
  1. connectionRequestTimeout:从连接池中获取连接的超时时间,超过该时间未拿到可用连接,会抛出ConnectionPoolTimeoutException: Timeout waiting for connection from pool
  2. connectTimeout:连接上服务器(握手成功)的时间,超出该时间抛出connect timeout
  3. socketTimeout:服务器返回数据(response)的时间,超过该时间抛出read timeout
连接池的大小

如果使用默认配置,连接池大小默认为20,即假设被请求接口响应时间为200ms,我们的程序每秒只能完成100个请求响应,剩余的则会陷入等待从连接池获取连接。则在某些高并发的场景中容易出现问题。

路由的大小

DefaultMaxPerRoute 是什么?

可以理解为 IP+端口的一条通路

例如连接池大小(MaxTotal)设置为300,路由连接数设置为200(DefaultMaxPerRoute),对于www.a.com与www.b.com两个路由每个路由的连接数不能超过200来说,两个路由的总连接数不能超过300。

关于setDefaultMaxPerRoute测试
// 服务端测试接口
@RestController
@RequestMapping("/test")
public class TestController {
    @RequestMapping("doTest")
    public Object test(){
        LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(3));
        return "ok";
    }

    @RequestMapping("doTest1")
    public Object tes1t(){
        LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(3));
        return "ok";
    }
}


// 客户端测试方法
public class ATest {

    public static Logger log = LoggerFactory.getLogger(ATest.class);
    public static void main(String[] args) {

        PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
        // 最大连接数-不设置默认20
        connectionManager.setMaxTotal(2);
        // 每个路由最大连接数-不设置默认2
        connectionManager.setDefaultMaxPerRoute(1);
        CloseableHttpClient httpClient = HttpClients.custom().setDefaultRequestConfig(
                        RequestConfig.custom()
                                // 连接服务器(握手)的超时时间
                                .setConnectTimeout(3000)
                                // 被请求服务器响应(response)的超时时间
                                .setSocketTimeout(50000)
                                // 从连接池中获取连接的超时时间
                                .setConnectionRequestTimeout(50000)
                                .build()
                ).setConnectionManager(connectionManager)
                .build();
        new Thread(()->{
            doGet(httpClient,"http://localhost:8080/test/doTest");
        }).start();
        new Thread(()->{
            doGet(httpClient,"http://localhost:8080/test/doTest1");
        }).start();

    }

    private static void doGet(CloseableHttpClient httpClient,String url) {
        HttpGet httpGet = new HttpGet(url);
        try {
            log.info("start");
            CloseableHttpResponse response = httpClient.execute(httpGet);
            log.info("message={}", EntityUtils.toString(response.getEntity()));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

结果

关于httpClient 使用的注意事项_第1张图片

配置setDefaultMaxPerRoute value为1 ,即同一个ip+端口只能存在一个连接,服务端模拟请求耗时3s,thread-0在请求3s后完成获得响应,并且我们可以看到thread-1实际是在等待thread-0完成请求释放连接后才开始请求,在请求6s后才获得响应

你可能感兴趣的:(Java,apache)