高并發下restTemplate的錯誤分析
1. 問題現象和分析
org.apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for connection
此問題很明顯是連接等待超時,而且是從連接池中獲取的連接。
那么就有一個很詫異的問題,這里哪來的連接池呢?然后我去跟蹤restTemplate的源碼發現,其底層是通過apache 的httpClient實現了連接池。那么問題就很明顯了。就是在并發量高的時候,可能會出現連接池不夠用。
2. 問題解決
- 既然分析出來是連接池不夠了,那么我們在構建restTemplate的時候配置其底層的httpClient連接池大小,以便提高高并發的時候RestTemplate的性能。
- 可以通過配置總體最大連接池(maxConnTotal)和單個路由連接最大數(maxConnPerRoute),默認是(20,2)
maxConnTotal
是整個連接池的大小,根據自己的業務需求進行設置
maxConnPerRoute
是單個路由連接的最大數,可以根據自己的業務需求進行設置
1
2
3
4
5
6
7
8
9
10
|
public RestTemplate restTemplate() { HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory(HttpClientBuilder.create() .setMaxConnTotal( 20 ) .setMaxConnPerRoute( 20 ) .build()); httpRequestFactory.setConnectionRequestTimeout( 10000 ); httpRequestFactory.setConnectTimeout( 10000 ); httpRequestFactory.setReadTimeout( 10000 ); return new RestTemplate(httpRequestFactory); } |
這樣就可以解決高并發下restTemplate連接池不夠的問題。提高其性能,使得調用restTemplate的程序性能------>
使用restTemplate出現的異常
1.org.springframework.web.client.UnknownContentTypeException: Could not extract response: no suitable HttpMessageConverter found for response type [class zycf.cloud.bean.SafetyResponseType] and content type [text/html]
除了所有的答案之外,如果碰巧收到了text/html,而你期望別的東西(即 application/json)
則可能表明服務器端發生了錯誤(比如404)并且返回了錯誤頁面而不是你的數據。
用postMan測試,果然是的,這個接口期望收到json數據,卻收到了HTML頁面
2.org.springframework.web.client.RestClientException: No HttpMessageConverter for java.util.HashMap and content type "multipart/form-data"
HashMap參數改為LinkedMultiValueMap
1
2
3
4
5
6
7
8
9
10
11
|
MultiValueMap<String, String> params = new LinkedMultiValueMap<>(); params.add( "clientId" ,ZHEJIANG_CLIENT_ID ); params.add( "nonce" , uuid); //隨機數 params.add( "timestamp" , dateString); //時間戳 params.add( "signature" , signature); //簽名 HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.MULTIPART_FORM_DATA); HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(params, headers); /** 發送請求*/ RestTemplate restTemplate = new RestTemplate(); SafetyResponseType safetyResponseType = restTemplate.postForObject(SAFETY_CERTIFICATE_URL, requestEntity, SafetyResponseType. class ); |
采用這種方法反序列化的時候,如果json字符串中有相同的key,存的時候值會以數組的方式保存,
比如我們在做表單提交的時候,表單數據中可能存在鍵相同值不同的情況,可以用這種方法存值。
以上為個人經驗,希望能給大家一個參考,也希望大家多多支持服務器之家。
原文鏈接:https://blog.csdn.net/qq_29738509/article/details/89962112