高并发下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