Рекомендации по настройке Apache Http Client 4.5.11 в производственной среде - PullRequest
0 голосов
/ 18 июня 2020

Ниже - мой ApacheHttpClient Spring bean, и мне интересно, подходит ли моя конфигурация для производства или мне нужно настроить какие-либо конфигурации? Может кто-нибудь, пожалуйста, поделитесь информацией, если вы используете последний Apache Http-клиент в производстве

@Service
public class ApacheHttpClient implements IHttpClient {
    private static final Logger              LOGGER                                             = Logger
            .getInstance(ApacheHttpClient.class);
    private static final int                 DEFAULT_MAX_TOTAL_CONNECTIONS                      = 400;
    private static final int                 DEFAULT_IDLE_CONNECTION_EVICTION_FREQUENCY_SECONDS = 300;
    private static final int                 DEFAULT_MAX_CONNECTIONS_PER_ROUTE                  = DEFAULT_MAX_TOTAL_CONNECTIONS;

    private static final int                 DEFAULT_CONNECTION_TIMEOUT_MILLISECONDS            = (60 * 1000);
    private static final int                 DEFAULT_READ_TIMEOUT_MILLISECONDS                  = (4 * 60 * 1000);
    private static final int                 DEFAULT_WAIT_TIMEOUT_MILLISECONDS                  = (60 * 1000);
    private static final int                 DEFAULT_VALIDATE_AFTER_INACTIVITY_MILLISECONDS     = (5 * 60 * 1000);

    private static final int                 DEFAULT_KEEP_ALIVE_MILLISECONDS                    = (5 * 60 * 1000);
    private static final int                 DEFAULT_REQUEST_RETRY                              = 2;

    @Autowired
    private SSLContextHelper                 customSSLContext;

    private int                              keepAlive                                          = DEFAULT_KEEP_ALIVE_MILLISECONDS;
    private int                              maxTotalConnections                                = DEFAULT_MAX_TOTAL_CONNECTIONS;

    private int                              maxConnectionsPerRoute                             = DEFAULT_MAX_CONNECTIONS_PER_ROUTE;
    private int                              connectTimeout                                     = DEFAULT_CONNECTION_TIMEOUT_MILLISECONDS;
    private int                              readTimeout                                        = DEFAULT_READ_TIMEOUT_MILLISECONDS;

    private int                              waitTimeout                                        = DEFAULT_WAIT_TIMEOUT_MILLISECONDS;
    private int                              requestRetry                                       = DEFAULT_REQUEST_RETRY;

    private CloseableHttpClient              httpClient;

    private ConnectionKeepAliveStrategy      keepAliveStrategy                                  = (response,
            context) -> {
                                                                                                    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) {}
                                                                                                        }
                                                                                                    }
                                                                                                    return keepAlive;
                                                                                                };


    @PostConstruct
    public void initializeApacheHttpClient() {

        // config timeout
        RequestConfig config = RequestConfig.custom()
                .setConnectTimeout(connectTimeout)
                .setConnectionRequestTimeout(waitTimeout)
                .setSocketTimeout(readTimeout).build();
        Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory> create()
                .register("http", PlainConnectionSocketFactory.INSTANCE)
                .register("https", new SSLConnectionSocketFactory(customSSLContext.getSSLContext())).build();

        PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);

        connManager.setMaxTotal(maxTotalConnections);

        // Increase default max connection per route
        connManager.setDefaultMaxPerRoute(maxConnectionsPerRoute);

        // Defines period of inactivity in milliseconds after which persistent connections must be re-validated prior to
        // being reused
        connManager.setValidateAfterInactivity(DEFAULT_VALIDATE_AFTER_INACTIVITY_MILLISECONDS);

        httpClient = HttpClients.custom().setKeepAliveStrategy(keepAliveStrategy).setConnectionManager(connManager)
                .setConnectionManagerShared(true).setSSLContext(customSSLContext.getSSLContext())
                .setDefaultRequestConfig(config)
                .setRetryHandler(new DefaultHttpRequestRetryHandler(requestRetry, true))
                .build();

        // detect idle and expired connections and close them
        IdleConnectionEvictor staleMonitor = new IdleConnectionEvictor(connManager, DEFAULT_IDLE_CONNECTION_EVICTION_FREQUENCY_SECONDS);
        staleMonitor.start();

        LOGGER.log(Level.INFO, "Initialize ApacheHttpClient is successful");
    }
}   

Ответы [ 3 ]

2 голосов
/ 18 июня 2020

Не уверен, можно ли дать четкий объективный ответ на этот вопрос. Не существует единого набора настроек, который работал бы для всех приложений. Ваша производственная среда и приложение будут уникальными.

Некоторые элементы для оценки:

  • Установите таймауты, соответствующие времени ответа, которое будут допускать ваши пользователи или вызывающие абоненты
  • Установите ограничения на количество подключений в соответствии с количеством подключений, необходимых для поддержки ожидаемого максимального трафика. c
  • Установите количество повторных попыток, подходящих для вашего приложения - будет ли ваше приложение допускать повторные попытки или это вызовет проблемы c поведения, потому что он воспроизводит запрос?

Вам также необходимо следить за своими журналами и метриками в реальном времени для соединений, использования памяти, времени отклика, тайм-аутов, ошибок и т. д. c.

Значения по умолчанию из Apache, вероятно, являются хорошими значениями по умолчанию. Apache Foundation и инженеры, которые помогают ему, имеют опыт и продумывают эти настройки по умолчанию.

1 голос
/ 18 июня 2020

В (неофициальном) руководстве по миграции Apache HttpClient 5.0 есть раздел, касающийся рекомендуемых параметров конфигурации и передовых методов для Apache версий HttpClient 4.5.x .

https://ok2c.github.io/httpclient-migration-guide/preparation.html

Две наиболее важные рекомендации:

  • Всегда повторно используйте экземпляры CloseableHttpClient. Их создание обходится дорого, но они также полностью потокобезопасны, поэтому несколько потоков могут использовать один и тот же экземпляр CloseableHttpClient для одновременного выполнения нескольких запросов, в полной мере используя постоянное повторное использование и объединение соединений.

  • Получение содержимого ответа непосредственно из потока содержимого и преобразование его в объект более высокого уровня без преобразования в промежуточную строку или массив байтов.

0 голосов
/ 17 июля 2020

Оказалось, что значение requestRetry больше 0 вызывает SocketException в нашей производственной среде, поэтому мы установили requestRetry = 0 и не получали никаких SocketException исключений

...