【问题标题】:What does PoolingHttpClientConnectionManager do when there is a temporary network outage?PoolingHttpClientConnectionManager 在临时网络中断时会做什么?
【发布时间】:2021-02-06 14:21:02
【问题描述】:

我正在将 PoolingHttpClientConnectionManager 添加到我们的 Spring Boot 服务中,该服务目前正在使用 RestTemplate 和 CloseableHttpClient 来发出请求。该服务正在使用 Apache httpcomponents 4.5。

如果出现临时网络中断会怎样?不良连接是否会从池中丢弃?或者在中断期间池是否充满了不良连接?中断结束后,池是否会自行恢复?还是我需要编写代码来检测它们并将它们从池中移除?

这是我目前的代码:

  @Bean
  public CloseableHttpClient closeableHttpClient() {
    CloseableHttpClient client = HttpClients.custom()
        .setDefaultRequestConfig(getDefaultRequestConfig())
        .setConnectionManager(poolingHttpClientConnectionManager())
        .setKeepAliveStrategy(getConnectionKeepAliveStrategy())
        .setRetryHandler(getHttpRequestRetryHandler())
        .build();

    return client;
  }

  @Bean
  public PoolingHttpClientConnectionManager poolingHttpClientConnectionManager() {

    Registry<ConnectionSocketFactory> socketFactoryRegistry = getSocketFactoryRegistry();
    PoolingHttpClientConnectionManager poolingConnectionManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);

    poolingConnectionManager.setMaxTotal(maxTotalConnections);
    poolingConnectionManager.setDefaultMaxPerRoute(maxRouteConnections);

    return poolingConnectionManager;
  }

  @Bean
  public Runnable idleConnectionMonitor(PoolingHttpClientConnectionManager pool) {
    return new Runnable() {
      @Override
      @Scheduled(fixedDelay = 20000)
      public void run() {
        if (pool != null) {
          pool.closeExpiredConnections();
          pool.closeIdleConnections(idleConnectionCloseTime, TimeUnit.MILLISECONDS);
        }
      }
    };
  }

  @Bean
  public TaskScheduler taskScheduler() {
    ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
    scheduler.setThreadNamePrefix("idleMonitor");
    scheduler.setPoolSize(idleMonitorPoolSize);
    return scheduler;
  }

  private RequestConfig getDefaultRequestConfig() {
    RequestConfig requestConfig = RequestConfig.custom()
        .setConnectTimeout(establishConnectionTimeout)
        .setConnectionRequestTimeout(fetchConnectionTimeout)
        .setSocketTimeout(socketInactivityTimeout)
        .build();
    return requestConfig;
  }

  private Registry<ConnectionSocketFactory> getSocketFactoryRegistry() {
    SSLConnectionSocketFactory socketFactory;
    socketFactory = new SSLConnectionSocketFactory(getSSLContext(), new String[] { sslProtocol }, null, new DefaultHostnameVerifier());

    Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder
        .<ConnectionSocketFactory> create().register("https", socketFactory)
        .build();

    return socketFactoryRegistry;
  }

  private SSLContext getSSLContext() {
    TrustStrategy acceptingTrustStrategy = null;

    try {
      KeyStore keyStore = KeyStore.getInstance(keyStoreType);
      keyStore.load(new FileInputStream(new File(keyStoreFile)), keyStorePwd.toCharArray());

      return new SSLContextBuilder()
          .loadTrustMaterial(keyStore, acceptingTrustStrategy)
          .loadKeyMaterial(keyStore, keyStorePwd.toCharArray())
          .build();
    } catch (KeyStoreException | IOException | NoSuchAlgorithmException | CertificateException | KeyManagementException | UnrecoverableKeyException e) {
      throw new RuntimeException(e);
    }
  }

  private ConnectionKeepAliveStrategy getConnectionKeepAliveStrategy() {
    return (httpResponse, httpContext) -> {
      HeaderIterator headerIterator = httpResponse.headerIterator(HTTP.CONN_KEEP_ALIVE);
      HeaderElementIterator elementIterator = new BasicHeaderElementIterator(headerIterator);

      while (elementIterator.hasNext()) {
        HeaderElement element = elementIterator.nextElement();
        String param = element.getName();
        String value = element.getValue();
        if (value != null && param.equalsIgnoreCase("timeout")) {
          return Long.parseLong(value) * 1000; // convert to ms
        }
      }

      return defaultKeepAliveTime;
    };
  }

  private DefaultHttpRequestRetryHandler getHttpRequestRetryHandler() {
    return new DefaultHttpRequestRetryHandler(httprequestRetryCount, false);
  }

【问题讨论】:

    标签: httpclient connection-pooling resttemplate apache-httpcomponents


    【解决方案1】:

    这些连接变得无效或“陈旧”。如果 HttpClient 已配置为在使用它们执行请求之前验证连接,则会检测并丢弃陈旧的连接。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-19
      • 1970-01-01
      • 1970-01-01
      • 2019-11-02
      • 1970-01-01
      • 2012-01-16
      • 1970-01-01
      • 2016-08-02
      相关资源
      最近更新 更多