Spring Boot 之 AsyncRestTemplate 连接池配置

2022-08-11 10:06:12

AsyncRestTemplate 连接池配置

通常业务中的 HTTP 请求都是同步调用的。如果请求响应比较慢,甚至请求超时,程序就必须等到请求返回以后才能继续执行,在某些场合下,我并不需要等待请求的结果,或者我不关心请求是否执行成功,需要继续执行之后的逻辑,就需要通过异步处理。

AsyncRestTemplate 是实现异步调用的工具。

AsyncRestTemplate 的连接池实现如下

配置文件类

/**
     * RestTemplate 客户端 Httpclient 的线程池配置
     *
     * @author fengxuechao
     * @version 0.1
     * @date 2019/11/12
     */@ConfigurationProperties(prefix="http-pool")@DatapublicclassHttpPoolProperties{/**
         * 最大线程数
         */private Integer maxTotal=20;/**
         * 默认线程数
         */private Integer defaultMaxPerRoute=10;/**
         * 连接上服务器(握手成功)的时间
         */private Integer connectTimeout=1000;/**
         * 从连接池中获取连接的超时时间
         */private Integer connectionRequestTimeout=3000;/**
         * 服务器返回数据(response)的时间
         */private Integer socketTimeout=5000;/**
         * 用于校验线程空闲的时间
         */private Integer validateAfterInactivity=7000;/**
         * 开启异步线程池
         */private Boolean async=false;}

连接池配置类

忽略SSL

/**
     * @author fengxuechao
     * @version 0.1
     * @date 2019/12/17
     */@Slf4j@ComponentpublicclassHttpClientHelper{public SSLContextgetSslContext(){// 在调用SSL之前需要重写验证方法,取消检测SSL
            X509TrustManager trustManager=newX509TrustManager(){@Overridepublic X509Certificate[]getAcceptedIssuers(){return null;}@OverridepublicvoidcheckClientTrusted(X509Certificate[] xcs, String str){}@OverridepublicvoidcheckServerTrusted(X509Certificate[] xcs, String str){}};
            SSLContext ctx= null;try{
                ctx= SSLContext.getInstance(SSLConnectionSocketFactory.TLS);
                ctx.init(null,newTrustManager[]{trustManager}, null);}catch(NoSuchAlgorithmException| KeyManagementException e){
                log.error("创建 SSL 失败", e);}assert ctx!= null;return ctx;}}

配置类

/**
     * @author fengxuechao
     * @version 0.1
     * @date 2019/12/17
     */@Slf4j@Configuration@ConditionalOnClass({HttpAsyncClient.class})@ConditionalOnProperty(prefix="http-pool", name="async", havingValue="true")@EnableConfigurationProperties(HttpPoolProperties.class)publicclassHttpAsyncClientConfig{@Autowiredprivate HttpPoolProperties httpPoolProperties;@Autowiredprivate HttpClientHelper helper;/**
         * 异步 Http 连接池
         *
         * @return
         */@Bean@ConditionalOnMissingBean(AsyncClientHttpRequestFactory.class)public AsyncClientHttpRequestFactoryasyncClientHttpRequestFactory(){
            HttpComponentsAsyncClientHttpRequestFactory factory=newHttpComponentsAsyncClientHttpRequestFactory(httpAsyncClient());
            factory.setConnectTimeout(httpPoolProperties.getConnectTimeout());
            factory.setReadTimeout(httpPoolProperties.getSocketTimeout());
            factory.setConnectionRequestTimeout(httpPoolProperties.getConnectionRequestTimeout());return factory;}/**
         * 异步 Http 客户端
         *
         * @return
         */@Bean("httpAsyncClient")@ConditionalOnMissingBean(HttpAsyncClient.class)public HttpAsyncClienthttpAsyncClient(){
            SSLContext sslContext= helper.getSslContext();
            Registry<SchemeIOSessionStrategy> registry= RegistryBuilder.<SchemeIOSessionStrategy>create().register("http", NoopIOSessionStrategy.INSTANCE).register("https",newSSLIOSessionStrategy(sslContext)).build();
            ConnectingIOReactor ioReactor= null;try{
                ioReactor=newDefaultConnectingIOReactor();}catch(IOReactorException e){
                log.error("构建异步连接失败", e);}assert ioReactor!= null;
            PoolingNHttpClientConnectionManager connectionManager=newPoolingNHttpClientConnectionManager(ioReactor, registry);
            connectionManager.setMaxTotal(httpPoolProperties.getMaxTotal());
            connectionManager.setDefaultMaxPerRoute(httpPoolProperties.getDefaultMaxPerRoute());
            RequestConfig requestConfig= RequestConfig.custom()//服务器返回数据(response)的时间,超过抛出read timeout.setSocketTimeout(httpPoolProperties.getSocketTimeout())//连接上服务器(握手成功)的时间,超出抛出connect timeout.setConnectTimeout(httpPoolProperties.getConnectTimeout())//从连接池中获取连接的超时时间,超时间未拿到可用连接,会抛出org.apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for connection from pool.setConnectionRequestTimeout(httpPoolProperties.getConnectionRequestTimeout()).build();return HttpAsyncClientBuilder.create().setDefaultRequestConfig(requestConfig).setConnectionManager(connectionManager).build();}}

AsyncRestTemplate 配置

/**
     * @author fengxuechao
     * @version 0.1
     * @date 2019/11/12
     */@Configuration@Import({HttpClientConfig.class})publicclassRestTemplateAutoConfiguration{/**
         * 异步 RestTemplate
         *
         * @return
         */@Bean("asyncRestTemplate")@ConditionalOnMissingBean@ConditionalOnBean(value={AsyncClientHttpRequestFactory.class, ClientHttpRequestFactory.class})public AsyncRestTemplateasyncRestTemplate(
                AsyncClientHttpRequestFactory asyncClientHttpRequestFactory,
                ClientHttpRequestFactory httpRequestFactory){
            RestTemplate restTemplate=newRestTemplate(httpRequestFactory);
            restTemplate.getMessageConverters().set(1,newStringHttpMessageConverter(StandardCharsets.UTF_8));returnnewAsyncRestTemplate(asyncClientHttpRequestFactory, restTemplate);}}
  • 作者:一年春又来
  • 原文链接:https://blog.csdn.net/Little_fxc/article/details/103583650
    更新时间:2022-08-11 10:06:12