Spring Boot 之 AsyncRestTemplate 连接池配置

AsyncRestTemplate 连接池配置

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

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

AsyncRestTemplate 的连接池实现如下

配置文件类

    /**
     * RestTemplate 客户端 Httpclient 的线程池配置
     *
     * @author fengxuechao
     * @version 0.1
     * @date 2019/11/12
     */
    @ConfigurationProperties(prefix = "http-pool")
    @Data
    public class HttpPoolProperties {
    
        /**
         * 最大线程数
         */
        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
    @Component
    public class HttpClientHelper {
    
        public SSLContext getSslContext() {
            // 在调用SSL之前需要重写验证方法,取消检测SSL
            X509TrustManager trustManager = new X509TrustManager() {
                @Override
                public X509Certificate[] getAcceptedIssuers() {
                    return null;
                }
    
                @Override
                public void checkClientTrusted(X509Certificate[] xcs, String str) {
                }
    
                @Override
                public void checkServerTrusted(X509Certificate[] xcs, String str) {
                }
            };
            SSLContext ctx = null;
            try {
                ctx = SSLContext.getInstance(SSLConnectionSocketFactory.TLS);
                ctx.init(null, new TrustManager[]{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)
    public class HttpAsyncClientConfig {
    
        @Autowired
        private HttpPoolProperties httpPoolProperties;
    
        @Autowired
        private HttpClientHelper helper;
    
        /**
         * 异步 Http 连接池
         *
         * @return
         */
        @Bean
        @ConditionalOnMissingBean(AsyncClientHttpRequestFactory.class)
        public AsyncClientHttpRequestFactory asyncClientHttpRequestFactory() {
            HttpComponentsAsyncClientHttpRequestFactory factory = new HttpComponentsAsyncClientHttpRequestFactory(httpAsyncClient());
            factory.setConnectTimeout(httpPoolProperties.getConnectTimeout());
            factory.setReadTimeout(httpPoolProperties.getSocketTimeout());
            factory.setConnectionRequestTimeout(httpPoolProperties.getConnectionRequestTimeout());
            return factory;
        }
    
        /**
         * 异步 Http 客户端
         *
         * @return
         */
        @Bean("httpAsyncClient")
        @ConditionalOnMissingBean(HttpAsyncClient.class)
        public HttpAsyncClient httpAsyncClient() {
            SSLContext sslContext = helper.getSslContext();
            Registry<SchemeIOSessionStrategy> registry = RegistryBuilder.<SchemeIOSessionStrategy>create()
                    .register("http", NoopIOSessionStrategy.INSTANCE)
                    .register("https", new SSLIOSessionStrategy(sslContext))
                    .build();
            ConnectingIOReactor ioReactor = null;
            try {
                ioReactor = new DefaultConnectingIOReactor();
            } catch (IOReactorException e) {
                log.error("构建异步连接失败", e);
            }
            assert ioReactor != null;
            PoolingNHttpClientConnectionManager connectionManager = new PoolingNHttpClientConnectionManager(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})
    public class RestTemplateAutoConfiguration {
    
        /**
         * 异步 RestTemplate
         *
         * @return
         */
        @Bean("asyncRestTemplate")
        @ConditionalOnMissingBean
        @ConditionalOnBean(value = {AsyncClientHttpRequestFactory.class, ClientHttpRequestFactory.class})
        public AsyncRestTemplate asyncRestTemplate(
                AsyncClientHttpRequestFactory asyncClientHttpRequestFactory,
                ClientHttpRequestFactory httpRequestFactory) {
            RestTemplate restTemplate = new RestTemplate(httpRequestFactory);
            restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
            return new AsyncRestTemplate(asyncClientHttpRequestFactory, restTemplate);
        }
    }
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值