0
votes

Meilleures pratiques pour la configuration d'Apache Http Client 4.5.11 en production

Voici mon ApacheHttpClient Spring bean et je me demande si la configuration que j'ai convient à la production ou si j'ai besoin de modifier des configurations? Quelqu'un peut-il partager des informations, si vous utilisez le dernier client Apache Http en production

@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");
    }
}   


0 commentaires

3 Réponses :


2
votes

Je ne sais pas si une réponse claire et objective peut être donnée à cette question. Il n'y a pas un seul ensemble de paramètres qui fonctionnera pour toutes les applications. Votre environnement de production et votre application seront uniques.

Certains éléments à évaluer sont:

  • Définissez des délais d'expiration cohérents avec les temps de réponse que vos utilisateurs ou appelants en amont toléreront
  • Définissez des limites de connexion cohérentes avec le nombre de connexions nécessaires pour prendre en charge votre trafic maximal attendu
  • Définir des tentatives appropriées pour votre application - Votre application tolérera-t-elle une nouvelle tentative ou cela induirait-il un comportement problématique car il relit une demande?

Vous devez également regarder la surveillance et observer vos journaux et métriques en temps réel pour les connexions, l'utilisation de la mémoire, les temps de réponse, les délais d'attente, les erreurs, etc.

Les valeurs par défaut d'Apache sont probablement de bonnes valeurs par défaut. La Fondation Apache et les ingénieurs qui l'assistent sont expérimentés et réfléchissent à ces valeurs par défaut.


0 commentaires

1
votes

Le guide de migration (non officiel) d'Apache HttpClient 5.0 contient une section concernant les paramètres de configuration recommandés et les bonnes pratiques pour les versions d'Apache HttpClient 4.5.x .

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

Deux recommandations les plus importantes:

  • Réutilisez toujours les instances CloseableHttpClient. Ils sont coûteux à créer, mais ils sont également entièrement thread-safe, de sorte que plusieurs threads peuvent utiliser la même instance de CloseableHttpClient pour exécuter plusieurs requêtes simultanément en tirant pleinement parti de la réutilisation persistante des connexions et du regroupement de connexions.

  • Consommez le contenu de la réponse directement à partir du flux de contenu et convertissez-le en objet de niveau supérieur sans le convertir en chaîne intermédiaire ou en tableau d'octets.


0 commentaires

0
votes

Il s'est avéré que le fait d'avoir une valeur de requestRetry supérieure à 0 provoquant SocketException dans notre environnement de production, nous avons donc défini le requestRetry = 0 et nous n'avons reçu aucune exception SocketException


0 commentaires