Разница между настройкой соединения через PoolingHttpClientConnectionManager и HttpClientBuilder

#java #spring #httpclient #apache-httpclient-4.x

#java #spring #httpclient #apache-httpclient-4.x

Вопрос:

У меня есть две конфигурации RestTemplate. Один настраивает соединение с помощью PoolingHttpClientConnectionManager, а другой настраивается напрямую через HttpClientBuilder. Оба имеют конфигурацию, связанную с подключением, с использованием HttpClient.

Ниже приведен один из них с HttpClientBuilder

 
        final HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
        httpClientBuilder.setMaxConnTotal(maxConnPerRoute);
        httpClientBuilder.setMaxConnPerRoute(maxConnPerRoute);
        httpClientBuilder.setConnectionReuseStrategy(new NoConnectionReuseStrategy());

        final HttpComponentsClientHttpRequestFactory httpComponentsClientHttpRequestFactory
            = new HttpComponentsClientHttpRequestFactory();

        httpComponentsClientHttpRequestFactory.setConnectTimeout(connectionTimeout);
        httpComponentsClientHttpRequestFactory.setReadTimeout(connectionTimeout);
        httpComponentsClientHttpRequestFactory.setHttpClient(httpClientBuilder.build());

        final BufferingClientHttpRequestFactory bufferingClientHttpRequestFactory =
            new BufferingClientHttpRequestFactory(httpComponentsClientHttpRequestFactory);
       final RestTemplate restTemplate = new RestTemplate(bufferingClientHttpRequestFactory);

  

Здесь мы напрямую настраиваем HttpClient следующим образом

 httpComponentsClientHttpRequestFactory.setHttpClient(httpClientBuilder.build());

  

Ниже PoolingHttpClientConnectionManager

    private ClientHttpRequestFactory clientHttpRequestFactory(final ConnectionPooling connectionPooling) {
        final PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
       
        connectionManager.setDefaultMaxPerRoute(connectionPooling.getMaxConnections());

        connectionManager.setMaxTotal(connectionPooling.getMaxConnections());

        final HttpClient httpclient = HttpClientBuilder
            .create()
            .setConnectionManager(connectionManager)
            .build();

        final HttpComponentsClientHttpRequestFactory connectionFactory =
            new HttpComponentsClientHttpRequestFactory(httpclient);
        connectionFactory.setConnectTimeout(connectionPooling.getConnectionTimeout());
        connectionFactory.setReadTimeout(connectionPooling.getReadTimeout());
        connectionFactory.setConnectionRequestTimeout(connectionPooling.getConnectionRequestTimeoutMillis());

        final IdleConnectionEvictor idleConnectionTimeoutThread =
            new IdleConnectionEvictor(connectionManager,
                connectionPooling.getIdleConnectionCheckMillis(), TimeUnit.MILLISECONDS,
                connectionPooling.getIdleConnectionTimeoutMillis(), TimeUnit.MILLISECONDS);
        idleConnectionTimeoutThread.start();

        return new BufferingClientHttpRequestFactory(connectionFactory);
    }
  

Здесь мы настраиваем как

 
        final HttpClient httpclient = HttpClientBuilder
            .create()
            .setConnectionManager(connectionManager)
            .build();
  

В чем разница между этими двумя конфигурациями? Будут ли они оба реагировать по-разному?

Ответ №1:

Они будут вести себя по-разному. Поскольку ваш первый HttpClientBuilder не устанавливает диспетчер соединений, это небезопасно для потоков. Полезно иметь диспетчер соединений, подобный вашему второму примеру, по многим причинам. Документация Apache здесь хорошо описывает преимущества диспетчера соединений:

Цель диспетчера HTTP-соединений — служить фабрикой для новых HTTP-соединений, управлять жизненным циклом постоянных соединений и синхронизировать доступ к постоянным соединениям, гарантируя, что только один поток может иметь доступ к соединению одновременно.