reatTemplate->httpClient連接池創(chuàng)建邏輯

httpClient連接池創(chuàng)建邏輯:

  1. org.springframework.boot.web.client.ClientHttpRequestFactorySupplier
    我們知道restTemplate只是一個模板類,具體的httpClent還是需要各種jar包類提供,下面的類就是一個選擇httpClient的具體實現(xiàn)過程,以及創(chuàng)建對應的工廠類:
// ClientHttpRequestFactory的供應商,根據(jù)類路徑上的可用實現(xiàn)檢測首選候選
public class ClientHttpRequestFactorySupplier implements Supplier<ClientHttpRequestFactory> {

   private static final Map<String, String> REQUEST_FACTORY_CANDIDATES;

   static {
       Map<String, String> candidates = new LinkedHashMap<>();
       candidates.put("org.apache.http.client.HttpClient","org.springframework.http.client.HttpComponentsClientHttpRequestFactory");
       candidates.put("okhttp3.OkHttpClient","org.springframework.http.client.OkHttp3ClientHttpRequestFactory");
       REQUEST_FACTORY_CANDIDATES = Collections.unmodifiableMap(candidates);
   }

   @Override
   public ClientHttpRequestFactory get() {
       for (Map.Entry<String, String> candidate : REQUEST_FACTORY_CANDIDATES.entrySet()) {
           ClassLoader classLoader = getClass().getClassLoader();
           if (ClassUtils.isPresent(candidate.getKey(), classLoader)) {
               Class<?> factoryClass = ClassUtils.resolveClassName(candidate.getValue(), classLoader);
               return (ClientHttpRequestFactory) BeanUtils.instantiateClass(factoryClass);
           }
       }
       return new SimpleClientHttpRequestFactory();
   }
}

此類通過定義好的類路徑去尋找最優(yōu)的httpClient提供商,分別按順序通過反射去篩選是否能找到apache.httpClient和okhttp的類,如果能找到apache.httpClient則去實例化對應的ClientHttpRequestFactory類,如果都找不到則創(chuàng)建默認的SimpleClientHttpRequestFactory類,此工廠中使用了默認的jdk.net包。對應的okhttp也有自己的工廠類OkHttp3ClientHttpRequestFactory。

  1. org.springframework.http.client.HttpComponentsClientHttpRequestFactory:74
    /**
     * 根據(jù)系統(tǒng)屬性,使用默認的HttpClient創(chuàng)建HttpComponentsClientHttpRequestFactory的新實例
     * Create a new instance of the {@code HttpComponentsClientHttpRequestFactory}
     * with a default {@link HttpClient} based on system properties.
     */
    public HttpComponentsClientHttpRequestFactory() {
        this.httpClient = HttpClients.createSystem();
    }

此類是spring為restTemplate提供的類,滿足了restTemplate使用HttpClient的需求
構造方法中調用了HttpClient的createSystem方法創(chuàng)建一個HttpClent實體,此構造方法在spring實例化restTemplate時會被調用。

  1. org.apache.http.impl.client.HttpClients:63
    /**
     * 使用基于系統(tǒng)屬性的默認配置創(chuàng)建CloseableHttpClient實例
     * Creates {@link CloseableHttpClient} instance with default
     * configuration based on system properties.
     */
    public static CloseableHttpClient createSystem() {
        return HttpClientBuilder.create().useSystemProperties().build();
    }

此類是httpClient提供的工廠方法類,提供了多種創(chuàng)建httpClient實例的工廠方法
調用了HttpClientBuilder的create()方法,默認使用系統(tǒng)屬性,調用了useSystemProperties()方法

  1. org.apache.http.impl.client.HttpClientBuilder
    public static HttpClientBuilder create() {    
        return new HttpClientBuilder();
    }
    // 在創(chuàng)建和配置默認實現(xiàn)時使用系統(tǒng)屬性
    public final HttpClientBuilder useSystemProperties() {    
        this.systemProperties = true;    
        return this;
    }

此類是CloseableHttpClient實例的構建器
其中最主的是build()方法,對各種參數(shù)進行了設置,其中一些重要部分的設置代碼如下所示:

    // 連接池初始化 調用PoolingHttpClientConnectionManager構造方法創(chuàng)建連接池
    final PoolingHttpClientConnectionManager poolingmgr = new PoolingHttpClientConnectionManager(        
        RegistryBuilder.<ConnectionSocketFactory>create()            
            .register("http", PlainConnectionSocketFactory.getSocketFactory())            
            .register("https", sslSocketFactoryCopy)            
            .build(),        
        null,        
        null,        
        dnsResolver, 
        connTimeToLive, 
        connTimeToLiveTimeUnit != null ? connTimeToLiveTimeUnit : TimeUnit.MILLISECONDS);
    if (defaultSocketConfig != null) {    
        poolingmgr.setDefaultSocketConfig(defaultSocketConfig);
    }
    if (defaultConnectionConfig != null) {    
        poolingmgr.setDefaultConnectionConfig(defaultConnectionConfig);
    }
    // httpClient默認連接數(shù)量的設置
    // 其中systemProperties參數(shù)代表創(chuàng)建的httpClient是否使用系統(tǒng)屬性,在上面的useSystemProperties()方法中設置為true
    // 如果 http.keepAlive(默認值為true) 為true,則會將 http.maxConnections(默認值為5) 屬性的值設置為同一個路由最多可以使用的連接數(shù),而連接池的最大連接數(shù)量為同一個路由最多使用連接數(shù)量的兩倍
    if (systemProperties) {    
        String s = System.getProperty("http.keepAlive", "true");    
        if ("true".equalsIgnoreCase(s)) {        
            s = System.getProperty("http.maxConnections", "5");        
            final int max = Integer.parseInt(s);        
            poolingmgr.setDefaultMaxPerRoute(max);        
            poolingmgr.setMaxTotal(2 * max);    
        }
    }
    if (maxConnTotal > 0) {    
        poolingmgr.setMaxTotal(maxConnTotal);
    }
    if (maxConnPerRoute > 0) {    
        poolingmgr.setDefaultMaxPerRoute(maxConnPerRoute);
    }
    connManagerCopy = poolingmgr;


org.apache.http.impl.conn.PoolingHttpClientConnectionManager

    public PoolingHttpClientConnectionManager(        
        final Registry<ConnectionSocketFactory> socketFactoryRegistry,        
        final HttpConnectionFactory<HttpRoute, ManagedHttpClientConnection> connFactory,        
        final SchemePortResolver schemePortResolver,        
        final DnsResolver dnsResolver,        
        final long timeToLive, final TimeUnit timeUnit) {    
        this(        
            new DefaultHttpClientConnectionOperator(socketFactoryRegistry, 
            schemePortResolver, dnsResolver),        
            connFactory,        
            timeToLive, timeUnit    
        );
    }
    // 真正創(chuàng)建創(chuàng)建連接池的構造方法
    public PoolingHttpClientConnectionManager(    
            final HttpClientConnectionOperator httpClientConnectionOperator,    
            final HttpConnectionFactory<HttpRoute, ManagedHttpClientConnection> connFactory,    
            final long timeToLive, final TimeUnit timeUnit) {    
        super();    
        this.configData = new ConfigData();    
        // 設置默認每個路由最大使用兩個連接,連接池總共有20個連接
        this.pool = new CPool(new InternalConnectionFactory(this.configData, connFactory), 2, 20, timeToLive, timeUnit);  
        this.pool.setValidateAfterInactivity(2000);    
        this.connectionOperator = Args.notNull(httpClientConnectionOperator, "HttpClientConnectionOperator");    
        this.isShutDown = new AtomicBoolean(false);
    }

org.apache.http.impl.conn.DefaultHttpClientConnectionOperator:

    public DefaultHttpClientConnectionOperator(        
            final Lookup<ConnectionSocketFactory> socketFactoryRegistry,        
            final SchemePortResolver schemePortResolver,        
            final DnsResolver dnsResolver) {    
        super();    
        Args.notNull(socketFactoryRegistry, "Socket factory registry");    
        this.socketFactoryRegistry = socketFactoryRegistry;    
        this.schemePortResolver = schemePortResolver != null ? schemePortResolver :        
        DefaultSchemePortResolver.INSTANCE;    
        this.dnsResolver = dnsResolver != null ? dnsResolver : SystemDefaultDnsResolver.INSTANCE;
    }


最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容