1. 程式人生 > >RestTemplate推送資料無響應的解決辦法

RestTemplate推送資料無響應的解決辦法

導讀

  • 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;
    //...
}
  • 本人原創,請勿抄襲,如果喜歡請轉載,謝謝。