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

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

  1. org.springframework.boot.web.client.ClientHttpRequestFactorySupplier
    我們知道restTemplate只是一個(gè)模板類叫潦,具體的httpClent還是需要各種jar包類提供箱蟆,下面的類就是一個(gè)選擇httpClient的具體實(shí)現(xiàn)過(guò)程斑粱,以及創(chuàng)建對(duì)應(yīng)的工廠類:
// ClientHttpRequestFactory的供應(yīng)商欧啤,根據(jù)類路徑上的可用實(shí)現(xiàn)檢測(cè)首選候選
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();
   }
}

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

  1. org.springframework.http.client.HttpComponentsClientHttpRequestFactory:74
    /**
     * 根據(jù)系統(tǒng)屬性比规,使用默認(rèn)的HttpClient創(chuàng)建HttpComponentsClientHttpRequestFactory的新實(shí)例
     * 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的需求
構(gòu)造方法中調(diào)用了HttpClient的createSystem方法創(chuàng)建一個(gè)HttpClent實(shí)體拦英,此構(gòu)造方法在spring實(shí)例化restTemplate時(shí)會(huì)被調(diào)用蜒什。

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

此類是httpClient提供的工廠方法類,提供了多種創(chuàng)建httpClient實(shí)例的工廠方法
調(diào)用了HttpClientBuilder的create()方法疤估,默認(rèn)使用系統(tǒng)屬性灾常,調(diào)用了useSystemProperties()方法

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

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

    // 連接池初始化 調(diào)用PoolingHttpClientConnectionManager構(gòu)造方法創(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默認(rèn)連接數(shù)量的設(shè)置
    // 其中systemProperties參數(shù)代表創(chuàng)建的httpClient是否使用系統(tǒng)屬性钞瀑,在上面的useSystemProperties()方法中設(shè)置為true
    // 如果 http.keepAlive(默認(rèn)值為true) 為true,則會(huì)將 http.maxConnections(默認(rèn)值為5) 屬性的值設(shè)置為同一個(gè)路由最多可以使用的連接數(shù)慷荔,而連接池的最大連接數(shù)量為同一個(gè)路由最多使用連接數(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)建連接池的構(gòu)造方法
    public PoolingHttpClientConnectionManager(    
            final HttpClientConnectionOperator httpClientConnectionOperator,    
            final HttpConnectionFactory<HttpRoute, ManagedHttpClientConnection> connFactory,    
            final long timeToLive, final TimeUnit timeUnit) {    
        super();    
        this.configData = new ConfigData();    
        // 設(shè)置默認(rèn)每個(gè)路由最大使用兩個(gè)連接雕什,連接池總共有20個(gè)連接
        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;
    }


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市显晶,隨后出現(xiàn)的幾起案子贷岸,更是在濱河造成了極大的恐慌,老刑警劉巖磷雇,帶你破解...
    沈念sama閱讀 211,639評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件偿警,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡唯笙,警方通過(guò)查閱死者的電腦和手機(jī)螟蒸,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,277評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)崩掘,“玉大人七嫌,你說(shuō)我怎么就攤上這事“” “怎么了诵原?”我有些...
    開(kāi)封第一講書人閱讀 157,221評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)枉疼。 經(jīng)常有香客問(wèn)我皮假,道長(zhǎng)鞋拟,這世上最難降的妖魔是什么骂维? 我笑而不...
    開(kāi)封第一講書人閱讀 56,474評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮贺纲,結(jié)果婚禮上航闺,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好潦刃,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,570評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布侮措。 她就那樣靜靜地躺著,像睡著了一般乖杠。 火紅的嫁衣襯著肌膚如雪分扎。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 49,816評(píng)論 1 290
  • 那天胧洒,我揣著相機(jī)與錄音畏吓,去河邊找鬼。 笑死卫漫,一個(gè)胖子當(dāng)著我的面吹牛菲饼,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播列赎,決...
    沈念sama閱讀 38,957評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼宏悦,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了包吝?” 一聲冷哼從身側(cè)響起饼煞,我...
    開(kāi)封第一講書人閱讀 37,718評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎诗越,沒(méi)想到半個(gè)月后派哲,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,176評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡掺喻,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,511評(píng)論 2 327
  • 正文 我和宋清朗相戀三年芭届,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片感耙。...
    茶點(diǎn)故事閱讀 38,646評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡褂乍,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出即硼,到底是詐尸還是另有隱情逃片,我是刑警寧澤,帶...
    沈念sama閱讀 34,322評(píng)論 4 330
  • 正文 年R本政府宣布只酥,位于F島的核電站褥实,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏裂允。R本人自食惡果不足惜损离,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,934評(píng)論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望绝编。 院中可真熱鬧僻澎,春花似錦貌踏、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,755評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至秉氧,卻和暖如春眷昆,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背汁咏。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,987評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工隙赁, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人梆暖。 一個(gè)月前我還...
    沈念sama閱讀 46,358評(píng)論 2 360
  • 正文 我出身青樓伞访,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親轰驳。 傳聞我的和親對(duì)象是個(gè)殘疾皇子厚掷,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,514評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容