java實(shí)用型-高并發(fā)下RestTemplate的正確使用說明
前言
如果java項(xiàng)目里有調(diào)用第三方的http接口,我們可以使用RestTemplate去遠(yuǎn)程訪問。也支持配置連接超時(shí)和響應(yīng)超時(shí),還可以配置各種長連接策略,也可以支持長連接預(yù)熱,在高并發(fā)下,合理的配置使用能夠有效提高第三方接口響應(yīng)時(shí)間。
一、RestTemplate是什么?
RestTemplate是Spring提供的用于訪問Rest服務(wù)的客戶端,RestTemplate提供了多種便捷訪問遠(yuǎn)程Http服務(wù)的方法,能夠大大提高客戶端的編寫效率。
二、如何使用
1.創(chuàng)建一個(gè)bean
以下代碼配置比較簡單,只設(shè)置了連接超時(shí)時(shí)間和響應(yīng)超時(shí)時(shí)間
/**
* restTemplate配置
*
* @author Songsong
* @date 2020-08-17 15:09
*/
@Configuration
public class RestTemplateConfiguration {
@Bean(name = "restTemplate")
public RestTemplate restTemplate() {
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
//設(shè)置連接超時(shí)時(shí)間1s
factory.setConnectTimeout(1000);
//設(shè)置讀取時(shí)間1s
factory.setReadTimeout(1000);
return new RestTemplate(factory);
}
}
2.使用步驟
在需要使用的地方使用@Resource或者@Autowired注入進(jìn)來
@Resource private RestTemplate restTemplate;
然后我們平常調(diào)用第三方的接口是get方式和post方式,restTemplate提供getForEntity和postForEntity方法支持這兩種方式,直接調(diào)用即可,源碼分別如下:
getForEntity方法:
public <T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Object... uriVariables) throws RestClientException {
RequestCallback requestCallback = this.acceptHeaderRequestCallback(responseType);
ResponseExtractor<ResponseEntity<T>> responseExtractor = this.responseEntityExtractor(responseType);
return (ResponseEntity)nonNull(this.execute(url, HttpMethod.GET, requestCallback, responseExtractor, uriVariables));
}
postForEntity方法:
public <T> ResponseEntity<T> postForEntity(String url, @Nullable Object request, Class<T> responseType, Object... uriVariables) throws RestClientException {
RequestCallback requestCallback = this.httpEntityCallback(request, responseType);
ResponseExtractor<ResponseEntity<T>> responseExtractor = this.responseEntityExtractor(responseType);
return (ResponseEntity)nonNull(this.execute(url, HttpMethod.POST, requestCallback, responseExtractor, uriVariables));
}
源碼中還有很多以上兩種其他的重載方法,以上是作者平常項(xiàng)目中用的最多的一種,參數(shù)有url(第三方http鏈接)、request是請求所需的參數(shù),responseType是返回類型里的泛型。
只需要解析返回的參數(shù)即可。
三、高并發(fā)下的RestTemplate使用
在平常的開發(fā)中,以上簡單的配置可能就夠用了,但是在高并發(fā)下,對接口響應(yīng)時(shí)間要求很高,所以我們需要盡量的提高第三方接口響應(yīng)時(shí)間。在RestTemplate中可以使用httpClient長連接,關(guān)于httpClient長連接的介紹我們可以參考:HTTPclient保持長連接
以下代碼我們設(shè)置了長連接預(yù)熱的功能,以及路由并發(fā)數(shù):
@Slf4j
@Configuration
public class RestTemplateConfiguration {
@Bean(name = "restTemplate")
public RestTemplate restTemplate() {
return getRestTemplate(3, "https://www.baidu.com/......");
}
private RestTemplate getRestTemplate(int maxTotal, String preHeatUrl) {
HttpComponentsClientHttpRequestFactory httpRequestFactory = httpComponentsClientHttpRequestFactory(maxTotal);
RestTemplate restTemplate = new RestTemplate(httpRequestFactory);
//解決首次預(yù)熱耗時(shí)長
if (StringUtils.isNotEmpty(preHeatUrl)) {
try {
restTemplate.postForEntity(preHeatUrl, "", String.class);
} catch (Exception e) {
log.error("preHeat url error:{}", e.getMessage());
}
}
return restTemplate;
}
/**
* ClientHttpRequestFactory接口的另一種實(shí)現(xiàn)方式(推薦使用),即:
* HttpComponentsClientHttpRequestFactory:底層使用Httpclient連接池的方式創(chuàng)建Http連接請求
*
* @return
*/
private HttpComponentsClientHttpRequestFactory httpComponentsClientHttpRequestFactory(int maxTotal) {
//Httpclient連接池,長連接保持時(shí)間
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(1, TimeUnit.HOURS);
//設(shè)置總連接數(shù)
connectionManager.setMaxTotal(maxTotal);
//設(shè)置同路由的并發(fā)數(shù)
connectionManager.setDefaultMaxPerRoute(maxTotal);
//設(shè)置header
List<Header> headers = new ArrayList<Header>();
headers.add(new BasicHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.3; rv:36.0) Gecko/20100101 Firefox/36.04"));
headers.add(new BasicHeader("Accept-Encoding", "gzip, deflate"));
headers.add(new BasicHeader("Accept-Language", "zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3"));
headers.add(new BasicHeader("Connection", "keep-alive"));
//創(chuàng)建HttpClient
HttpClient httpClient = HttpClientBuilder.create()
.setConnectionManager(connectionManager)
.setDefaultHeaders(headers)
.setRetryHandler(new DefaultHttpRequestRetryHandler(3, true)) //設(shè)置重試次數(shù)
.setKeepAliveStrategy(new DefaultConnectionKeepAliveStrategy()) //設(shè)置保持長連接
.build();
//創(chuàng)建HttpComponentsClientHttpRequestFactory實(shí)例
HttpComponentsClientHttpRequestFactory requestFactory =
new HttpComponentsClientHttpRequestFactory(httpClient);
//設(shè)置客戶端和服務(wù)端建立連接的超時(shí)時(shí)間
requestFactory.setConnectTimeout(10000);
//設(shè)置客戶端從服務(wù)端讀取數(shù)據(jù)的超時(shí)時(shí)間
requestFactory.setReadTimeout(5000);
//設(shè)置從連接池獲取連接的超時(shí)時(shí)間,不宜過長
requestFactory.setConnectionRequestTimeout(2000);
//緩沖請求數(shù)據(jù),默認(rèn)為true。通過POST或者PUT大量發(fā)送數(shù)據(jù)時(shí),建議將此更改為false,以免耗盡內(nèi)存
requestFactory.setBufferRequestBody(false);
return requestFactory;
}
1.設(shè)置預(yù)熱功能
我們可以看到,在getRestTemplate方法中,
return restTemplate;
之前先請求了一次,也就是說在需要使用第三方接口調(diào)用的service層注入的時(shí)候,提前先調(diào)用了一次,根據(jù)長連接的特性,一般第一次連接的時(shí)間較長,使用完之后,這個(gè)連接并不會馬上回收掉,在一定的時(shí)間還是存活狀態(tài),所以在高并發(fā)下,經(jīng)過預(yù)熱后的接口響應(yīng)時(shí)間會大幅提高。
2.合理設(shè)置maxtotal數(shù)量
我們可以看到以下代碼
//設(shè)置總連接數(shù) connectionManager.setMaxTotal(maxTotal);
我們可以看到這一行,maxTotal是設(shè)置總連接數(shù),這個(gè)設(shè)置需要根據(jù)接口的響應(yīng)時(shí)間以及需要支持的QPS來設(shè)置,比如接口響應(yīng)時(shí)間是100ms,需要支持的QPS為5000,也就是5000/s,那么一個(gè)長連接1s就是能夠處理10個(gè)請求,那么總共需要maxTotal為500個(gè),這個(gè)就是設(shè)置的大概數(shù)量,但是有時(shí)候QPS不是那么穩(wěn)定,所以具體設(shè)置多少得視具體情況而定。
RestTemplate深度解析可以參考:RestTemplate深度解析
總結(jié)
以上就是關(guān)于RestTemplate的使用介紹,其實(shí)平常使用下還好,看不出來什么問題,但是一旦高并發(fā)情況下,預(yù)熱和設(shè)置總連接數(shù)還有并發(fā)數(shù)以及其他的相關(guān)配置就顯得尤為重要,具體的配置還是得經(jīng)過實(shí)驗(yàn)才能得知,沒有最好,只有更好,以上就是作者在高并發(fā)活動中的一些實(shí)際經(jīng)歷,希望可以幫助到你?。?!如有錯(cuò)誤或未考慮完全的地方,望不吝賜教,也希望大家多多支持腳本之家!
相關(guān)文章
SpringBoot使用Caffeine實(shí)現(xiàn)緩存的示例代碼
本文主要介紹了SpringBoot使用Caffeine實(shí)現(xiàn)緩存的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-07-07
Spring?Boot?使用?Disruptor?做內(nèi)部高性能消息隊(duì)列
這篇文章主要介紹了Spring?Boot?使用?Disruptor?做內(nèi)部高性能消息隊(duì)列,工作中遇到項(xiàng)目使用Disruptor做消息隊(duì)列,對你沒看錯(cuò),不是Kafka,也不是rabbitmq。Disruptor有個(gè)最大的優(yōu)點(diǎn)就是快,還有一點(diǎn)它是開源的哦,下面做個(gè)簡單的記錄2022-06-06
Go Java算法之外觀數(shù)列實(shí)現(xiàn)方法示例詳解
這篇文章主要為大家介紹了Go Java算法外觀數(shù)列實(shí)現(xiàn)的方法示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08
Quarkus中實(shí)現(xiàn)Resteasy的文件上傳下載操作
這篇文章主要為大家介紹了Quarkus中實(shí)現(xiàn)Resteasy的文件上傳下載的操作過程步驟,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步2022-02-02

