最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

springboot restTemplate連接池整合方式

 更新時(shí)間:2021年10月23日 11:28:34   作者:程猿薇蔦  
這篇文章主要介紹了springboot restTemplate連接池整合方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

springboot restTemplate連接池整合

restTemplate

使用http連接池能夠減少連接建立與釋放的時(shí)間,提升http請(qǐng)求的性能。如果客戶端每次請(qǐng)求都要和服務(wù)端建立新的連接,即三次握手將會(huì)非常耗時(shí)。本文介紹如何在Springboot中集成http連接池;基于restTemplate+httpclient實(shí)現(xiàn)。

引入apache httpclient

        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.5.6</version>
        </dependency>

RestTemplate配置類

import org.apache.http.client.HttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.springframework.boot.context.properties.ConfigurationProperties;
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.http.client.SimpleClientHttpRequestFactory;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.web.client.RestTemplate;
import java.nio.charset.Charset;
import java.util.List;
import java.util.concurrent.TimeUnit;
/**
 * 實(shí)際開發(fā)中要避免每次http請(qǐng)求都實(shí)例化httpclient
 * restTemplate默認(rèn)會(huì)復(fù)用連接,保證restTemplate單例即可
 * 參考資料:
 * https://www.cnblogs.com/xrq730/p/10963689.html
 * https://halfrost.com/advance_tcp/
 */
@Configuration
public class RestTemplateConfig {
    @Bean
    RestTemplate restTemplate(ClientHttpRequestFactory clientHttpRequestFactory) {
        RestTemplate restTemplate = new RestTemplate(clientHttpRequestFactory);
        List<HttpMessageConverter<?>> messageConverters = restTemplate.getMessageConverters();
        for (HttpMessageConverter c : messageConverters) {
            if (c instanceof StringHttpMessageConverter) {
                ((StringHttpMessageConverter) c).setDefaultCharset(Charset.forName("utf-8"));
            }
        }
        return restTemplate;
    }
    @Bean
    @ConfigurationProperties(prefix = "spring.resttemplate")
    HttpClientProperties httpClientProperties() {
        return new HttpClientProperties();
    }
    @Bean
    ClientHttpRequestFactory clientHttpRequestFactory(HttpClientProperties httpClientProperties) {
        //如果不使用HttpClient的連接池,則使用restTemplate默認(rèn)的SimpleClientHttpRequestFactory,底層基于HttpURLConnection
        if (!httpClientProperties.isUseHttpClientPool()) {
            SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
            factory.setConnectTimeout(httpClientProperties.getConnectTimeout());
            factory.setReadTimeout(httpClientProperties.getReadTimeout());
            return factory;
        }
        //HttpClient4.3及以上版本不手動(dòng)設(shè)置HttpClientConnectionManager,默認(rèn)就會(huì)使用連接池PoolingHttpClientConnectionManager
        HttpClient httpClient = HttpClientBuilder.create().setMaxConnTotal(httpClientProperties.getMaxTotalConnect())
                .setMaxConnPerRoute(httpClientProperties.getMaxConnectPerRoute()).evictExpiredConnections()
                .evictIdleConnections(5000, TimeUnit.MILLISECONDS).build();
        HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(httpClient);
        factory.setConnectTimeout(httpClientProperties.getConnectTimeout());
        factory.setReadTimeout(httpClientProperties.getReadTimeout());
        factory.setConnectionRequestTimeout(httpClientProperties.getConnectionRequestTimeout());
        return factory;
    }
}

RestTemplate連接池配置參數(shù)

public class HttpClientProperties {
    /**
     * 是否使用httpclient連接池
     */
    private boolean useHttpClientPool = false;
    /**
     * 從連接池中獲得一個(gè)connection的超時(shí)時(shí)間
     */
    private int connectionRequestTimeout = 3000;
    /**
     * 建立連接超時(shí)時(shí)間
     */
    private int connectTimeout = 3000;
    /**
     * 建立連接后讀取返回?cái)?shù)據(jù)的超時(shí)時(shí)間
     */
    private int readTimeout = 5000;
    /**
     * 連接池的最大連接數(shù),0代表不限
     */
    private int maxTotalConnect = 128;
    /**
     * 每個(gè)路由的最大連接數(shù)
     */
    private int maxConnectPerRoute = 32;
    public int getConnectionRequestTimeout() {
        return connectionRequestTimeout;
    }
    public void setConnectionRequestTimeout(int connectionRequestTimeout) {
        this.connectionRequestTimeout = connectionRequestTimeout;
    }
    public int getConnectTimeout() {
        return connectTimeout;
    }
    public void setConnectTimeout(int connectTimeout) {
        this.connectTimeout = connectTimeout;
    }
    public int getReadTimeout() {
        return readTimeout;
    }
    public void setReadTimeout(int readTimeout) {
        this.readTimeout = readTimeout;
    }
    public int getMaxTotalConnect() {
        return maxTotalConnect;
    }
    public void setMaxTotalConnect(int maxTotalConnect) {
        this.maxTotalConnect = maxTotalConnect;
    }
    public int getMaxConnectPerRoute() {
        return maxConnectPerRoute;
    }
    public void setMaxConnectPerRoute(int maxConnectPerRoute) {
        this.maxConnectPerRoute = maxConnectPerRoute;
    }
    public boolean isUseHttpClientPool() {
        return useHttpClientPool;
    }
    public void setUseHttpClientPool(boolean useHttpClientPool) {
        this.useHttpClientPool = useHttpClientPool;
    }
}

application.properties

spring.resttemplate.connectionRequestTimeout=3000
spring.resttemplate.connectTimeout=3000
spring.resttemplate.readTimeout=10000
spring.resttemplate.maxTotalConnect=256
spring.resttemplate.maxConnectPerRoute=128
spring.resttemplate.useHttpClientPool=true

測(cè)試帶連接池的RestTemplate

import com.alibaba.fastjson.JSON;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
@RunWith(SpringRunner.class)
@SpringBootTest
public class RestTemplateTest {
    /**
     * 免費(fèi)查詢號(hào)碼歸屬地接口
     */
    public String testUrl = "https://tcc.taobao.com/cc/json/mobile_tel_segment.htm";
    @Autowired
    RestTemplate restTemplate;
    @Test
    public void testRest() {
        HttpHeaders headers = new HttpHeaders();
        headers.set("Accept", "application/json");
        HttpEntity entity = new HttpEntity(headers);
        long start = System.currentTimeMillis();
        for (int i = 0; i < 1000; i++) {
            String tel = getRandomTel();
            UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(testUrl).queryParam("tel", tel);
            System.out.println("發(fā)送請(qǐng)求:" + builder.build().encode().toUri());
            long startInner = System.currentTimeMillis();
            ResponseEntity<String> getDistrictRes = restTemplate.exchange(builder.build().encode().toUri(), HttpMethod.GET, entity, String.class);
            long endInner = System.currentTimeMillis();
            System.out.print("costPerRequest:" + (endInner - startInner) + ",i=" + i + "," + Thread.currentThread().getName());
            String resJson = getDistrictRes.getBody().split("=")[1];
            String carrier = (String) JSON.parseObject(resJson).get("carrier");
            System.out.println("," + tel + ",歸屬地:" + carrier);
        }
        long end = System.currentTimeMillis();
        System.out.println("costTotal:" + (end - start));
    }
    private String getRandomTel() {
        List<String> telList = Arrays.asList("18120168516", "15952044278", "15537788259", "18751872329", "13913329187");
        int index = ThreadLocalRandom.current().nextInt(telList.size());
        return telList.get(index);
    }
}

測(cè)試比較發(fā)現(xiàn),如果不設(shè)置ClientHttpRequestFactory,resttemplate默認(rèn)會(huì)使用SimpleClientHttpRequestFactory,底層基于HttpURLConnection;這種方式和手動(dòng)設(shè)置帶連接池的httpComponentsClientHttpRequestFactory性能差別不大,基于httpclient的連接池性能稍有優(yōu)勢(shì),不是太明顯。

不管是使用restTemplate默認(rèn)的SimpleClientHttpRequestFactory還是使用httpclient提供的HttpComponentsClientHttpRequestFactory,都會(huì)進(jìn)行連接復(fù)用,即只有第一次請(qǐng)求耗時(shí)較高,后面的請(qǐng)求都復(fù)用連接。

使用httpclient可以設(shè)置evictExpiredConnections、evictIdleConnections進(jìn)行定時(shí)清理過期、閑置連接。底層是開啟了一個(gè)線程去執(zhí)行清理任務(wù),因此注意不能多次實(shí)例化httpclient相關(guān)的實(shí)例,會(huì)導(dǎo)致不斷創(chuàng)建線程。

注意事項(xiàng)

實(shí)際開發(fā)中要避免每次http請(qǐng)求都實(shí)例化httpclient

restTemplate默認(rèn)會(huì)復(fù)用連接,保證restTemplate單例即

RestTemplate 配置http連接池

import java.nio.charset.Charset;
import java.util.Iterator;
import java.util.List;
import org.apache.http.client.HttpClient;
import org.apache.http.conn.HttpClientConnectionManager;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.springframework.boot.web.client.RestTemplateBuilder;
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.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.web.client.RestTemplate;
 
@Configuration
public class RestTemplateUtil{ 
    @Bean
    public RestTemplate restTemplate(RestTemplateBuilder builder) {
	RestTemplate restTemplate = builder.build();
	restTemplate.setRequestFactory(clientHttpRequestFactory()); 
        // 使用 utf-8 編碼集的 conver 替換默認(rèn)的 conver(默認(rèn)的 string conver 的編碼集為"ISO-8859-1")
        List<HttpMessageConverter<?>> messageConverters = restTemplate.getMessageConverters();
        Iterator<HttpMessageConverter<?>> iterator = messageConverters.iterator();
        while (iterator.hasNext()) {
            HttpMessageConverter<?> converter = iterator.next();
            if (converter instanceof StringHttpMessageConverter) {
                iterator.remove();
            }
        }
        messageConverters.add(new StringHttpMessageConverter(Charset.forName("UTF-8"))); 
        return restTemplate;
    }	
    
    @Bean
    public HttpClientConnectionManager poolingConnectionManager() {
	PoolingHttpClientConnectionManager poolingConnectionManager = new PoolingHttpClientConnectionManager();
	poolingConnectionManager.setMaxTotal(1000); // 連接池最大連接數(shù)  
	poolingConnectionManager.setDefaultMaxPerRoute(100); // 每個(gè)主機(jī)的并發(fā)
	return poolingConnectionManager;
    }
    
    @Bean
    public HttpClientBuilder httpClientBuilder() {
	HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
        //設(shè)置HTTP連接管理器
	httpClientBuilder.setConnectionManager(poolingConnectionManager());
	return httpClientBuilder;
    }
    
    @Bean
    public ClientHttpRequestFactory clientHttpRequestFactory() { 
	HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory();
	clientHttpRequestFactory.setHttpClient(httpClientBuilder().build());
	clientHttpRequestFactory.setConnectTimeout(6000); // 連接超時(shí),毫秒		
	clientHttpRequestFactory.setReadTimeout(6000); // 讀寫超時(shí),毫秒		
	return clientHttpRequestFactory;
    }
}

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • java獲取鍵盤輸入的數(shù)字,并進(jìn)行排序的方法

    java獲取鍵盤輸入的數(shù)字,并進(jìn)行排序的方法

    今天小編就為大家分享一篇java獲取鍵盤輸入的數(shù)字,并進(jìn)行排序的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2018-07-07
  • Java收集的雪花算法代碼詳解

    Java收集的雪花算法代碼詳解

    這篇文章主要介紹了Java實(shí)現(xiàn)雪花算法的詳細(xì)代碼,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-10-10
  • Java實(shí)現(xiàn)解析第三方接口返回的json

    Java實(shí)現(xiàn)解析第三方接口返回的json

    在實(shí)際開發(fā)過程中,免不了和其他公司進(jìn)行聯(lián)調(diào),調(diào)用第三方接口,這個(gè)時(shí)候我們就需要根據(jù)對(duì)方返回的數(shù)據(jù)進(jìn)行解析,獲得我們想要的字段,下面我們就來看看具體有哪些方法吧
    2024-01-01
  • IDEA不編譯除了.java之外的文件的解決辦法(推薦)

    IDEA不編譯除了.java之外的文件的解決辦法(推薦)

    這篇文章主要介紹了IDEA不編譯除了.java之外的文件的解決辦法,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-08-08
  • mybatis使用@mapkey獲取的結(jié)果的鍵(key)為null問題

    mybatis使用@mapkey獲取的結(jié)果的鍵(key)為null問題

    這篇文章主要介紹了mybatis使用@mapkey獲取的結(jié)果的鍵(key)為null問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-06-06
  • Java中HTTP GET方法調(diào)用帶有body的問題解決

    Java中HTTP GET方法調(diào)用帶有body的問題解決

    這篇文章主要為大家詳細(xì)介紹了Java如何解決HTTP GET方法調(diào)用帶有body的問題,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以參考一下
    2024-02-02
  • Spring?Boot實(shí)現(xiàn)文件上傳下載

    Spring?Boot實(shí)現(xiàn)文件上傳下載

    這篇文章主要為大家詳細(xì)介紹了Spring?Boot實(shí)現(xiàn)文件上傳下載,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-08-08
  • Java中字符數(shù)組和字符串與StringBuilder和字符串轉(zhuǎn)換的講解

    Java中字符數(shù)組和字符串與StringBuilder和字符串轉(zhuǎn)換的講解

    今天小編就為大家分享一篇關(guān)于Java中字符數(shù)組和字符串與StringBuilder和字符串轉(zhuǎn)換的講解,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧
    2019-03-03
  • 詳解SpringBoot中的統(tǒng)一結(jié)果返回與統(tǒng)一異常處理

    詳解SpringBoot中的統(tǒng)一結(jié)果返回與統(tǒng)一異常處理

    這篇文章主要將通過詳細(xì)的討論和實(shí)例演示來幫助你更好地理解和應(yīng)用Spring Boot中的統(tǒng)一結(jié)果返回和統(tǒng)一異常處理,感興趣的小伙伴可以了解下
    2024-03-03
  • java語言描述Redis分布式鎖的正確實(shí)現(xiàn)方式

    java語言描述Redis分布式鎖的正確實(shí)現(xiàn)方式

    這篇文章主要介紹了java語言描述Redis分布式鎖的正確實(shí)現(xiàn)方式,具有一定借鑒價(jià)值,需要的朋友可以參考下。
    2017-12-12

最新評(píng)論

和林格尔县| 青河县| 金塔县| 铜川市| 革吉县| 鸡泽县| 湘潭县| 乾安县| 天门市| 诸城市| 湘潭县| 璧山县| 义马市| 兴业县| 长泰县| 临安市| 芒康县| 固始县| 丹阳市| 嘉义县| 双柏县| 微山县| 绥滨县| 确山县| 通榆县| 蒙自县| 永和县| 兴山县| 广元市| 西和县| 新疆| 昭苏县| 灵台县| 象州县| 大姚县| 南投市| 景东| 滕州市| 宿州市| 广丰县| 平度市|