<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          RestTemplate 連接池:記一次壓測調(diào)優(yōu)

          共 3399字,需瀏覽 7分鐘

           ·

          2020-08-22 15:15

          [ 用大白話講解復(fù)雜的技術(shù) ]

          這是我的第?53?篇原創(chuàng)文章
          作者 l 會點代碼的大叔(CodeDaShu)??


          最近工作上有些調(diào)整,進(jìn)入了另一個項目組,本周在給一個接口做壓力測試的過程中,發(fā)現(xiàn) TPS 波動比較大:單臺服務(wù)器的 TPS 在 1000 到 200 之間波動,發(fā)現(xiàn)問題后我們做了這幾件事兒逐一排問題。


          1. 排除其他操作對壓測的影響

          觀察數(shù)據(jù)的時間戳,發(fā)現(xiàn)在壓測過程中有頻發(fā)的數(shù)據(jù)寫入,先暫停跑批操作,再次壓測波動依然存在;


          2. 代碼檢查,降低數(shù)據(jù)庫查詢次數(shù)

          做代碼檢查,這個功能需要查詢六次數(shù)據(jù)庫、調(diào)用一次接口才能獲得所有數(shù)據(jù),經(jīng)過優(yōu)化后將查詢數(shù)據(jù)庫的次數(shù)降低為三次,再次壓測后 TPS 有所提升,但是波動的情況還存在;


          3. 分階段壓測,縮小問題范圍

          因為該接口的邏輯是本地邏輯 + 遠(yuǎn)程調(diào)用,于是先做了擋板單壓本地邏輯,再單獨壓遠(yuǎn)程接口,兩次壓測不存在波動的問題,所以基本上可以確定是調(diào)用接口的過程中存在一些問題;


          4. 排除 GC 問題

          調(diào)用接口的過程中創(chuàng)建了太多的 Java 對象,可能會引發(fā)頻發(fā)的 GC 操作;但是通過對 JVM 的觀察排除了這個問題;


          5. 初步確認(rèn)問題

          最后將問題的范圍縮小,懷疑是 RestTemplate 的使用問題;


          RestTemplate 是 Spring 提供的用于訪問 Http 接口的客戶端框架,能夠大大提高客戶端的編寫效率,大部分基于 SSM 或 Spring Boot 的項目會使用 RestTemplate,翻了一下項目中 RestTemplate Config,只配置了超時時間:

          @Configurationpublic class RestTemplateConfig {    @Bean    public RestTemplate restTemplate(){        SimpleClientHttpRequestFactory factory =new SimpleClientHttpRequestFactory();        factory.setConnectTimeout(30000);        factory.setReadTimeout(10000);        RestTemplate restTemplate = new RestTemplate(factory);        return restTemplate;    }}


          RestTemplate 默認(rèn)的?

          ClientHttpRequestFactor?

          SimpleClientHttpRequestFactory,其中的 createRequest 方法,每次都會創(chuàng)建一個新的連接,建立連接本身就是一個費時費力的操作,如果頻繁地對一個接口發(fā)起調(diào)用,每次都創(chuàng)建連接會造成極大的資源浪費,而且若連接不能及時釋放,就會因為無法建立新的連接導(dǎo)致后面的請求阻塞。

          @Overridepublic ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) throws IOException {  HttpURLConnection connection = openConnection(uri.toURL(), this.proxy);  prepareConnection(connection, httpMethod.name());
          if (this.bufferRequestBody) { return new SimpleBufferingClientHttpRequest(connection, this.outputStreaming); } else { return new SimpleStreamingClientHttpRequest(connection, this.chunkSize, this.outputStreaming); }}


          看到這種情況處理起來也算簡單:弄個連接池;


          創(chuàng)建 RestTemplate連接線程池,就需要使用其他的 HTTP 庫(默認(rèn)使用的是 JDK 自己的),比如 HttpComponents、Netty、OkHttp,在這里我選擇的是 HttpComponents 。


          1. 引入依賴:

          <dependency>    <groupId>org.apache.httpcomponentsgroupId>    <artifactId>httpcoreartifactId>    <version>version>dependency>
          <dependency> <groupId>org.apache.httpcomponentsgroupId> <artifactId>httpclientartifactId> <version>version>dependency>


          2. 修改 RestTemplateConfig :

          @Configurationpublic?class?RestTemplateConfig?{    @Bean    public RestTemplate restTemplate() {        return new RestTemplate(httpRequestFactory());    }
          @Bean public ClientHttpRequestFactory httpRequestFactory() { return new HttpComponentsClientHttpRequestFactory(httpClient()); }
          @Bean public HttpClient httpClient() { Registry registry = RegistryBuilder.create() .register("http", PlainConnectionSocketFactory.getSocketFactory()) .register("https", SSLConnectionSocketFactory.getSocketFactory()) .build(); PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(registry); //設(shè)置整個連接池最大連接數(shù) connectionManager.setMaxTotal(400); //路由是對maxTotal的細(xì)分 connectionManager.setDefaultMaxPerRoute(100); RequestConfig requestConfig = RequestConfig.custom() .setSocketTimeout(30000) //返回數(shù)據(jù)的超時時間????????????????.setConnectTimeout(10000)?//連接上服務(wù)器的超時時間 .setConnectionRequestTimeout(1000) //從連接池中獲取連接的超時時間 .build(); return HttpClientBuilder.create() .setDefaultRequestConfig(requestConfig) .setConnectionManager(connectionManager) .build(); }}


          修改完成之后再次壓測,單機(jī) TPS 穩(wěn)定在 1200,打完收工。


          期待分享

          如果您喜歡本文,請點個“在看”或分享到朋友圈,這將是對我最大的鼓勵。



          瀏覽 173
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  青青青久| 天天操天天日天天干 | 亚洲女同在线 | 一级不卡毛片 | 激情综合网五月丁香 |