您好,登錄后才能下訂單哦!
這篇文章主要介紹“java實(shí)用型高并發(fā)下RestTemplate的正確使用方法是什么”,在日常操作中,相信很多人在java實(shí)用型高并發(fā)下RestTemplate的正確使用方法是什么問(wèn)題上存在疑惑,小編查閱了各式資料,整理出簡(jiǎn)單好用的操作方法,希望對(duì)大家解答”java實(shí)用型高并發(fā)下RestTemplate的正確使用方法是什么”的疑惑有所幫助!接下來(lái),請(qǐng)跟著小編一起來(lái)學(xué)習(xí)吧!
如果java項(xiàng)目里有調(diào)用第三方的http接口,我們可以使用RestTemplate去遠(yuǎn)程訪問(wèn)。也支持配置連接超時(shí)和響應(yīng)超時(shí),還可以配置各種長(zhǎng)連接策略,也可以支持長(zhǎng)連接預(yù)熱,在高并發(fā)下,合理的配置使用能夠有效提高第三方接口響應(yīng)時(shí)間。
RestTemplate是Spring提供的用于訪問(wèn)Rest服務(wù)的客戶端,RestTemplate提供了多種便捷訪問(wèn)遠(yuǎn)程Http服務(wù)的方法,能夠大大提高客戶端的編寫(xiě)效率。
以下代碼配置比較簡(jiǎn)單,只設(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); } }
在需要使用的地方使用@Resource或者@Autowired注入進(jìn)來(lái)
@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是請(qǐng)求所需的參數(shù),responseType是返回類(lèi)型里的泛型。
只需要解析返回的參數(shù)即可。
在平常的開(kāi)發(fā)中,以上簡(jiǎn)單的配置可能就夠用了,但是在高并發(fā)下,對(duì)接口響應(yīng)時(shí)間要求很高,所以我們需要盡量的提高第三方接口響應(yīng)時(shí)間。在RestTemplate中可以使用httpClient長(zhǎng)連接,關(guān)于httpClient長(zhǎng)連接的介紹我們可以參考:HTTPclient保持長(zhǎng)連接
以下代碼我們?cè)O(shè)置了長(zhǎng)連接預(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í)長(zhǎng) 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連接請(qǐng)求 * * @return */ private HttpComponentsClientHttpRequestFactory httpComponentsClientHttpRequestFactory(int maxTotal) { //Httpclient連接池,長(zhǎng)連接保持時(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è)置保持長(zhǎng)連接 .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í)間,不宜過(guò)長(zhǎng) requestFactory.setConnectionRequestTimeout(2000); //緩沖請(qǐng)求數(shù)據(jù),默認(rèn)為true。通過(guò)POST或者PUT大量發(fā)送數(shù)據(jù)時(shí),建議將此更改為false,以免耗盡內(nèi)存 requestFactory.setBufferRequestBody(false); return requestFactory; }
我們可以看到,在getRestTemplate方法中,
return restTemplate;
之前先請(qǐng)求了一次,也就是說(shuō)在需要使用第三方接口調(diào)用的service層注入的時(shí)候,提前先調(diào)用了一次,根據(jù)長(zhǎng)連接的特性,一般第一次連接的時(shí)間較長(zhǎng),使用完之后,這個(gè)連接并不會(huì)馬上回收掉,在一定的時(shí)間還是存活狀態(tài),所以在高并發(fā)下,經(jīng)過(guò)預(yù)熱后的接口響應(yīng)時(shí)間會(huì)大幅提高。
我們可以看到以下代碼
//設(shè)置總連接數(shù) connectionManager.setMaxTotal(maxTotal);
我們可以看到這一行,maxTotal是設(shè)置總連接數(shù),這個(gè)設(shè)置需要根據(jù)接口的響應(yīng)時(shí)間以及需要支持的QPS來(lái)設(shè)置,比如接口響應(yīng)時(shí)間是100ms,需要支持的QPS為5000,也就是5000/s,那么一個(gè)長(zhǎng)連接1s就是能夠處理10個(gè)請(qǐng)求,那么總共需要maxTotal為500個(gè),這個(gè)就是設(shè)置的大概數(shù)量,但是有時(shí)候QPS不是那么穩(wěn)定,所以具體設(shè)置多少得視具體情況而定。
RestTemplate深度解析可以參考:RestTemplate深度解析
到此,關(guān)于“java實(shí)用型高并發(fā)下RestTemplate的正確使用方法是什么”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識(shí),請(qǐng)繼續(xù)關(guān)注億速云網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)?lái)更多實(shí)用的文章!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。