From 3ff009d971eb134d3848fcac6d0602e8da618a19 Mon Sep 17 00:00:00 2001 From: liuliaozhong Date: Wed, 6 Dec 2023 14:46:22 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E5=AE=9A=E6=97=B6=E4=BB=BB=E5=8A=A1?= =?UTF-8?q?=E5=81=B6=E7=8E=B0=E5=90=AF=E5=8A=A8=E5=A4=B1=E8=B4=A5=20#2138?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/util/http/HttpHelperFactory.java | 5 + ...JobHttpClientConnectionManagerFactory.java | 9 +- src/backend/job-crontab/build.gradle | 2 + .../bk/job/crontab/config/FeignConfig.java | 115 ++++++++++++++++++ 4 files changed, 126 insertions(+), 5 deletions(-) create mode 100644 src/backend/job-crontab/service-job-crontab/src/main/java/com/tencent/bk/job/crontab/config/FeignConfig.java diff --git a/src/backend/commons/common/src/main/java/com/tencent/bk/job/common/util/http/HttpHelperFactory.java b/src/backend/commons/common/src/main/java/com/tencent/bk/job/common/util/http/HttpHelperFactory.java index 9ec28d2b1c..fec007edea 100644 --- a/src/backend/commons/common/src/main/java/com/tencent/bk/job/common/util/http/HttpHelperFactory.java +++ b/src/backend/commons/common/src/main/java/com/tencent/bk/job/common/util/http/HttpHelperFactory.java @@ -78,9 +78,14 @@ private static CloseableHttpClient getHttpClient(int connRequestTimeout, log.error("", e); } httpClientBuilder.setConnectionManager( + // esb的keep-alive时间为90s,需要<90s,防止连接超时抛出org.apache.http.NoHttpResponseException: + // The target server failed to respond + // 因此,timeToLive使用34s JobHttpClientConnectionManagerFactory.createWatchableConnectionManager( maxConnPerRoute, maxConnTotal, + 34, + TimeUnit.SECONDS, sslSocketFactory )); httpClient = httpClientBuilder.build(); diff --git a/src/backend/commons/common/src/main/java/com/tencent/bk/job/common/util/http/JobHttpClientConnectionManagerFactory.java b/src/backend/commons/common/src/main/java/com/tencent/bk/job/common/util/http/JobHttpClientConnectionManagerFactory.java index da2b2c5c73..0a0af85a68 100644 --- a/src/backend/commons/common/src/main/java/com/tencent/bk/job/common/util/http/JobHttpClientConnectionManagerFactory.java +++ b/src/backend/commons/common/src/main/java/com/tencent/bk/job/common/util/http/JobHttpClientConnectionManagerFactory.java @@ -57,11 +57,10 @@ public class JobHttpClientConnectionManagerFactory { public static HttpClientConnectionManager createWatchableConnectionManager( int maxConnPerRoute, int maxConnTotal, + long timeToLive, + TimeUnit timeUnit, LayeredConnectionSocketFactory sslSocketFactory ) { - // esb的keep-alive时间为90s,需要<90s,防止连接超时抛出org.apache.http.NoHttpResponseException: - // The target server failed to respond - // 因此,timeToLive使用34s final PoolingHttpClientConnectionManager poolingmgr = new WatchablePoolingHttpClientConnectionManager( RegistryBuilder.create() @@ -71,8 +70,8 @@ public static HttpClientConnectionManager createWatchableConnectionManager( new WatchableManagedHttpClientConnectionFactory(), null, null, - 34, - TimeUnit.SECONDS + timeToLive, + timeUnit ); if (defaultConnectionConfig != null) { poolingmgr.setDefaultConnectionConfig(defaultConnectionConfig); diff --git a/src/backend/job-crontab/build.gradle b/src/backend/job-crontab/build.gradle index af956a0a3c..88d160904d 100644 --- a/src/backend/job-crontab/build.gradle +++ b/src/backend/job-crontab/build.gradle @@ -39,6 +39,8 @@ subprojects { compileOnly 'org.projectlombok:lombok' annotationProcessor 'org.projectlombok:lombok' implementation(group: 'org.apache.commons', name: 'commons-pool2') + implementation "io.github.openfeign:feign-httpclient" + implementation "org.springframework.retry:spring-retry" testImplementation 'org.springframework.boot:spring-boot-starter-test' testImplementation 'org.junit.jupiter:junit-jupiter' } diff --git a/src/backend/job-crontab/service-job-crontab/src/main/java/com/tencent/bk/job/crontab/config/FeignConfig.java b/src/backend/job-crontab/service-job-crontab/src/main/java/com/tencent/bk/job/crontab/config/FeignConfig.java new file mode 100644 index 0000000000..2250ba3771 --- /dev/null +++ b/src/backend/job-crontab/service-job-crontab/src/main/java/com/tencent/bk/job/crontab/config/FeignConfig.java @@ -0,0 +1,115 @@ +/* + * Tencent is pleased to support the open source community by making BK-JOB蓝鲸智云作业平台 available. + * + * Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-JOB蓝鲸智云作业平台 is licensed under the MIT License. + * + * License for BK-JOB蓝鲸智云作业平台: + * -------------------------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and + * to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO + * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +package com.tencent.bk.job.crontab.config; + +import com.tencent.bk.job.common.util.http.JobHttpClientConnectionManagerFactory; +import feign.Client; +import feign.httpclient.ApacheHttpClient; +import lombok.extern.slf4j.Slf4j; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.conn.HttpClientConnectionManager; +import org.apache.http.conn.socket.LayeredConnectionSocketFactory; +import org.apache.http.conn.ssl.SSLConnectionSocketFactory; +import org.apache.http.conn.ssl.TrustSelfSignedStrategy; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.impl.client.StandardHttpRequestRetryHandler; +import org.apache.http.ssl.SSLContexts; +import org.springframework.cloud.client.loadbalancer.LoadBalancedRetryFactory; +import org.springframework.cloud.client.loadbalancer.LoadBalancerClient; +import org.springframework.cloud.client.loadbalancer.LoadBalancerProperties; +import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory; +import org.springframework.cloud.openfeign.loadbalancer.RetryableFeignBlockingLoadBalancerClient; +import org.springframework.cloud.openfeign.support.FeignHttpClientProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.security.KeyManagementException; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.util.concurrent.TimeUnit; + +@Slf4j +@Configuration +public class FeignConfig { + + @Bean + public HttpClientConnectionManager feignClientConnectionManager(FeignHttpClientProperties httpClientProperties) { + LayeredConnectionSocketFactory sslSocketFactory = null; + try { + sslSocketFactory = new SSLConnectionSocketFactory( + SSLContexts.custom() + .loadTrustMaterial(null, new TrustSelfSignedStrategy()) + .build() + ); + } catch (NoSuchAlgorithmException | KeyManagementException | KeyStoreException e) { + log.error("Fail to create SSLConnectionSocketFactory", e); + } + return JobHttpClientConnectionManagerFactory.createWatchableConnectionManager( + httpClientProperties.getMaxConnectionsPerRoute(), + httpClientProperties.getMaxConnections(), + // 服务端Keep-Alive timeout为60s,此处45s+4s(默认10s)<60s即可 + 45, + TimeUnit.SECONDS, + sslSocketFactory + ); + } + + public ApacheHttpClient getApacheHttpClient(FeignHttpClientProperties httpClientProperties, + HttpClientConnectionManager feignClientConnectionManager) { + RequestConfig defaultRequestConfig = RequestConfig.custom() + .setConnectTimeout(httpClientProperties.getConnectionTimeout()) + .setRedirectsEnabled(httpClientProperties.isFollowRedirects()).build(); + HttpClientBuilder httpClientBuilder = HttpClientBuilder.create() + .setDefaultRequestConfig(defaultRequestConfig) + .evictExpiredConnections() + .evictIdleConnections(4000, TimeUnit.MILLISECONDS) + .disableAutomaticRetries() + .disableAuthCaching() + .disableCookieManagement(); + httpClientBuilder.setRetryHandler(new StandardHttpRequestRetryHandler()); + CloseableHttpClient httpClient; + httpClientBuilder.setConnectionManager(feignClientConnectionManager); + httpClient = httpClientBuilder.build(); + return new ApacheHttpClient(httpClient); + } + + @Bean + public Client feignClient(FeignHttpClientProperties httpClientProperties, + HttpClientConnectionManager feignClientConnectionManager, + LoadBalancerClient loadBalancerClient, + LoadBalancedRetryFactory loadBalancedRetryFactory, + LoadBalancerProperties properties, + LoadBalancerClientFactory loadBalancerClientFactory) { + ApacheHttpClient delegate = getApacheHttpClient(httpClientProperties, feignClientConnectionManager); + return new RetryableFeignBlockingLoadBalancerClient( + delegate, + loadBalancerClient, + loadBalancedRetryFactory, + properties, + loadBalancerClientFactory + ); + } +}