content: package com.gitee.pifeng.monitoring.server.config;
  
  import lombok.extern.slf4j.Slf4j;
  import org.apache.http.client.config.RequestConfig;
  import org.apache.http.config.Registry;
  import org.apache.http.config.RegistryBuilder;
  import org.apache.http.config.SocketConfig;
  import org.apache.http.conn.DnsResolver;
  import org.apache.http.conn.HttpConnectionFactory;
  import org.apache.http.conn.ManagedHttpClientConnection;
  import org.apache.http.conn.routing.HttpRoute;
  import org.apache.http.conn.socket.ConnectionSocketFactory;
  import org.apache.http.conn.socket.PlainConnectionSocketFactory;
  import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
  import org.apache.http.impl.DefaultConnectionReuseStrategy;
  import org.apache.http.impl.client.CloseableHttpClient;
  import org.apache.http.impl.client.DefaultConnectionKeepAliveStrategy;
  import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
  import org.apache.http.impl.client.HttpClients;
  import org.apache.http.impl.conn.ManagedHttpClientConnectionFactory;
  import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
  import org.apache.http.impl.conn.SystemDefaultDnsResolver;
  import org.apache.http.impl.io.DefaultHttpRequestWriterFactory;
  import org.apache.http.impl.io.DefaultHttpResponseParserFactory;
  import org.springframework.context.annotation.Bean;
  import org.springframework.context.annotation.Configuration;
  import org.springframework.http.client.ClientHttpRequestFactory;
  import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
  import org.springframework.web.client.RestTemplate;
  
  import java.util.concurrent.TimeUnit;
  
  /**
   * <p>
   * 配置RestTemplate，RestTemplate是Spring提供的用于访问Rest服务的客户端，提供了多种便捷访问远程Http服务的方法，能够大大提高客户端的编写效率
   * </p>
   *
   * @author 皮锋
   * @custom.date 2020年1月20日 上午10:58:31
   */
  @Configuration
  @Slf4j
  public class RestTemplateConfig {
  
      /**
       * <p>
       * 构造RestTemplate实例，把RestTemplate实例作为一个JavaBean交给Spring管理。
       * </p>
       *
       * @return {@link RestTemplate}
       * @author 皮锋
       * @custom.date 2020年3月4日 下午3:46:33
       */
      @Bean
      public RestTemplate restTemplate() {
          RestTemplate restTemplate = new RestTemplate(this.httpRequestFactory());
          log.info("RestTemplate配置成功！");
          return restTemplate;
      }
  
      /**
       * <p>
       * 构造ClientHttpRequestFactory实例
       * </p>
       *
       * @return {@link ClientHttpRequestFactory}
       * @author 皮锋
       * @custom.date 2021/12/6 16:41
       */
      @Bean
      public ClientHttpRequestFactory httpRequestFactory() {
          return new HttpComponentsClientHttpRequestFactory(this.httpClient());
      }
  
      /**
       * <p>
       * 构造CloseableHttpClient实例
       * </p>
       *
       * @return {@link CloseableHttpClient}
       * @author 皮锋
       * @custom.date 2021/12/6 16:43
       */
      @Bean(destroyMethod = "close")
      public CloseableHttpClient httpClient() {
          // 注册访问协议相关的Socket工厂
          Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
                  // 配置同时支持 HTTP 和 HTPPS
                  .register("http", PlainConnectionSocketFactory.INSTANCE)
                  .register("https", SSLConnectionSocketFactory.getSystemSocketFactory())
                  .build();
          // HttpConnection工厂：配置写请求/解析响应处理器
          HttpConnectionFactory<HttpRoute, ManagedHttpClientConnection> connectionFactory
                  = new ManagedHttpClientConnectionFactory(DefaultHttpRequestWriterFactory.INSTANCE, DefaultHttpResponseParserFactory.INSTANCE);
          // DNS解析器
          DnsResolver dnsResolver = SystemDefaultDnsResolver.INSTANCE;
          // 创建池化连接管理器
          PoolingHttpClientConnectionManager manager = new PoolingHttpClientConnectionManager(socketFactoryRegistry, connectionFactory, dnsResolver);
          // 默认Socket配置
          SocketConfig defaultSocketConfig = SocketConfig.custom().setTcpNoDelay(true).build();
          manager.setDefaultSocketConfig(defaultSocketConfig);
          // 设置整个连接池的最大连接数
          manager.setMaxTotal(300);
          // 每个路由的默认最大连接，每个路由实际最大连接数由DefaultMaxPerRoute控制，而MaxTotal是整个池子的最大数
          // 设置过小无法支持大并发(ConnectionPoolTimeoutException) Timeout waiting for connection from pool
          // 每个路由的最大连接数
          manager.setDefaultMaxPerRoute(200);
          // 在从连接池获取连接时，连接不活跃多长时间后需要进行一次验证，默认为2s
          manager.setValidateAfterInactivity(30 * 1000);
          //默认请求配置
          RequestConfig defaultRequestConfig = RequestConfig.custom()
                  // 设置连接超时时间，15s
                  .setConnectTimeout(15000)
                  // 设置等待数据超时时间，15s
                  .setSocketTimeout(15000)
                  // 设置从连接池获取连接的等待超时时间,15s
                  .setConnectionRequestTimeout(15000)
                  .build();
          // 创建HttpClient
          CloseableHttpClient httpClient = HttpClients.custom()
                  .setConnectionManager(manager)
                  // 连接池不是共享模式
                  .setConnectionManagerShared(false)
                  // 定期回收空闲连接
                  .evictIdleConnections(60, TimeUnit.SECONDS)
                  // 定期回收过期连接
                  .evictExpiredConnections()
                  // 连接存活时间，如果不设置，则根据长连接信息决定
                  .setConnectionTimeToLive(60, TimeUnit.SECONDS)
                  // 设置默认请求配置
                  .setDefaultRequestConfig(defaultRequestConfig)
                  // 连接重用策略，即是否能keepAlive
                  .setConnectionReuseStrategy(DefaultConnectionReuseStrategy.INSTANCE)
                  // 长连接配置，即获取长连接生产多长时间
                  .setKeepAliveStrategy(DefaultConnectionKeepAliveStrategy.INSTANCE)
                  // 设置重试次数，默认是3次
                  .setRetryHandler(new DefaultHttpRequestRetryHandler(3, true))
                  .build();
          log.info("服务端HTTP连接池初始化成功！");
          return httpClient;
      }
  
  }
  