RestTemplate推送資料無響應的解決辦法
阿新 • • 發佈:2019-01-25
導讀
- A平臺在給其他平臺推送資料時,A平臺呼叫其他平臺介面成功,但無返回結果,導致消費機資料不消費。
邏輯分析
- 應該有推送多長時間無返回結果就為推送失敗,這樣的邏輯。
程式碼分析
推送原始碼
RestTemplate restTemplate = new RestTemplate();
ResponseResult responseResult = restTemplate.postForObject(syncUrl, formEntity, ResponseResult.class);
- 感覺restTemplate有配置,但是查看了RestTemplate類,並沒有相關配置。經過百度發現:SimpleClientHttpRequestFactory類。
SimpleClientHttpRequestFactory 部分原始碼
public class SimpleClientHttpRequestFactory implements ClientHttpRequestFactory, AsyncClientHttpRequestFactory {
private static final int DEFAULT_CHUNK_SIZE = 4096;
private Proxy proxy;
private boolean bufferRequestBody = true;
private int chunkSize = 4096 ;
private int connectTimeout = -1;
private int readTimeout = -1;
private boolean outputStreaming = true;
private AsyncListenableTaskExecutor taskExecutor;
//...
public void setConnectTimeout(int connectTimeout) {
this.connectTimeout = connectTimeout;
}
//...
public void setReadTimeout(int readTimeout) {
this.readTimeout = readTimeout;
}
}
- 發現有 setConnectTimeout 和 setReadTimeout 方法,且預設值為 -1。進而猜測是這裡導致一直卡死。
修改推送程式碼(方式一)
SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
requestFactory.setConnectTimeout(20000);
requestFactory.setReadTimeout(20000);
RestTemplate restTemplate = new RestTemplate(requestFactory);
思考
- 有沒有配置檔案可以進行配置,而不用每次set配置呢?
編寫配置 RestTemplateConfiguration 類 (方式二)
@Configuration
@ConditionalOnClass(value = {RestTemplate.class, HttpClient.class})
public class RestTemplateConfiguration {
@Value("${remote.maxTotalConnect:0}")
private int maxTotalConnect; //連線池的最大連線數預設為0
@Value("${remote.maxConnectPerRoute:200}")
private int maxConnectPerRoute; //單個主機的最大連線數
@Value("${remote.connectTimeout:2000}")
private int connectTimeout; //連線超時預設2s
@Value("${remote.readTimeout:30000}")
private int readTimeout; //讀取超時預設30s
private ClientHttpRequestFactory createFactory() {
if (this.maxTotalConnect <= 0) {
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
factory.setConnectTimeout(this.connectTimeout);
factory.setReadTimeout(this.readTimeout);
return factory;
}
HttpClient httpClient = HttpClientBuilder.create().setMaxConnTotal(this.maxTotalConnect)
.setMaxConnPerRoute(this.maxConnectPerRoute).build();
HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(
httpClient);
factory.setConnectTimeout(this.connectTimeout);
factory.setReadTimeout(this.readTimeout);
return factory;
}
@Bean
@ConditionalOnMissingBean(RestTemplate.class)
public RestTemplate getRestTemplate() {
RestTemplate restTemplate = new RestTemplate(this.createFactory());
List<HttpMessageConverter<?>> converterList = restTemplate.getMessageConverters();
HttpMessageConverter<?> converterTarget = null;
for (HttpMessageConverter<?> item : converterList) {
if (StringHttpMessageConverter.class == item.getClass()) {
converterTarget = item;
break;
}
}
if (null != converterTarget) {
converterList.remove(converterTarget);
}
converterList.add(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
converterList.add(new FastJsonHttpMessageConverter4());
return restTemplate;
}
}
該配置檔案的使用
@Service
@Import({RestTemplateConfiguration.class})
public class AServiceImpl implements AService {
private final ADao aDao;
//...
}
- 本人原創,請勿抄襲,如果喜歡請轉載,謝謝。