From 23feca20750d44722d3c59a50177d805f3458ffe Mon Sep 17 00:00:00 2001 From: byteblogs168 <598092184@qq.com> Date: Fri, 3 Nov 2023 18:33:21 +0800 Subject: [PATCH] =?UTF-8?q?feat:=202.4.0=201.=20=E9=87=8D=E8=AF=95?= =?UTF-8?q?=E6=89=A7=E8=A1=8C=E8=B6=85=E6=97=B6=E6=97=B6=E9=97=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/sql/easy_retry_mysql.sql | 1 + .../persistence/po/SceneConfig.java | 2 + .../server/common/client/RequestBuilder.java | 17 ++++--- .../common/client/RequestInterceptor.java | 45 +++++++++++++++++++ .../common/client/RpcClientInvokeHandler.java | 14 +++--- .../common/config/RestTemplateConfig.java | 35 +++++++++++---- .../actor/exec/ExecCallbackUnitActor.java | 1 + .../dispatch/actor/exec/ExecUnitActor.java | 1 + .../model/request/SceneConfigRequestVO.java | 6 +++ 9 files changed, 103 insertions(+), 19 deletions(-) create mode 100644 easy-retry-server/easy-retry-server-common/src/main/java/com/aizuda/easy/retry/server/common/client/RequestInterceptor.java diff --git a/doc/sql/easy_retry_mysql.sql b/doc/sql/easy_retry_mysql.sql index 464a9f8d..c533e175 100644 --- a/doc/sql/easy_retry_mysql.sql +++ b/doc/sql/easy_retry_mysql.sql @@ -135,6 +135,7 @@ CREATE TABLE `scene_config` `back_off` tinyint(4) NOT NULL DEFAULT '1' COMMENT '1、默认等级 2、固定间隔时间 3、CRON 表达式', `trigger_interval` varchar(16) NOT NULL DEFAULT '' COMMENT '间隔时长', `deadline_request` bigint(20) unsigned NOT NULL DEFAULT '60000' COMMENT 'Deadline Request 调用链超时 单位毫秒', + `executor_timeout` int(11) unsigned NOT NULL DEFAULT '5' COMMENT '任务执行超时时间,单位秒', `route_key` tinyint(4) NOT NULL DEFAULT '4' COMMENT '路由策略', `description` varchar(256) NOT NULL DEFAULT '' COMMENT '描述', `create_dt` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', diff --git a/easy-retry-datasource/easy-retry-datasource-template/src/main/java/com/aizuda/easy/retry/template/datasource/persistence/po/SceneConfig.java b/easy-retry-datasource/easy-retry-datasource-template/src/main/java/com/aizuda/easy/retry/template/datasource/persistence/po/SceneConfig.java index 8381ef2b..70394ec6 100644 --- a/easy-retry-datasource/easy-retry-datasource-template/src/main/java/com/aizuda/easy/retry/template/datasource/persistence/po/SceneConfig.java +++ b/easy-retry-datasource/easy-retry-datasource-template/src/main/java/com/aizuda/easy/retry/template/datasource/persistence/po/SceneConfig.java @@ -31,6 +31,8 @@ public class SceneConfig implements Serializable { private Integer routeKey; + private Integer executorTimeout; + private LocalDateTime createDt; private LocalDateTime updateDt; diff --git a/easy-retry-server/easy-retry-server-common/src/main/java/com/aizuda/easy/retry/server/common/client/RequestBuilder.java b/easy-retry-server/easy-retry-server-common/src/main/java/com/aizuda/easy/retry/server/common/client/RequestBuilder.java index 107a8849..76157b0c 100644 --- a/easy-retry-server/easy-retry-server-common/src/main/java/com/aizuda/easy/retry/server/common/client/RequestBuilder.java +++ b/easy-retry-server/easy-retry-server-common/src/main/java/com/aizuda/easy/retry/server/common/client/RequestBuilder.java @@ -26,6 +26,7 @@ public class RequestBuilder { private boolean failover; private int routeKey; private String allocKey; + private Integer executorTimeout; public static RequestBuilder newBuilder() { @@ -42,10 +43,15 @@ public class RequestBuilder { return this; } -// public RequestBuilder groupName(String groupName) { -// this.groupName = groupName; -// return this; -// } + public RequestBuilder executorTimeout(Integer executorTimeout) { + if (Objects.isNull(executorTimeout)) { + return this; + } + + Assert.isTrue(executorTimeout > 0, () -> new EasyRetryServerException("executorTimeout can not less 0")); + this.executorTimeout = executorTimeout; + return this; + } public RequestBuilder failRetry(boolean failRetry) { this.failRetry = failRetry; @@ -101,7 +107,8 @@ public class RequestBuilder { } RpcClientInvokeHandler clientInvokeHandler = new RpcClientInvokeHandler( - nodeInfo.getGroupName(), nodeInfo, failRetry, retryTimes, retryInterval, retryListener, routeKey, allocKey, failover); + nodeInfo.getGroupName(), nodeInfo, failRetry, retryTimes, retryInterval, + retryListener, routeKey, allocKey, failover, executorTimeout); return (T) Proxy.newProxyInstance(clintInterface.getClassLoader(), new Class[]{clintInterface}, clientInvokeHandler); diff --git a/easy-retry-server/easy-retry-server-common/src/main/java/com/aizuda/easy/retry/server/common/client/RequestInterceptor.java b/easy-retry-server/easy-retry-server-common/src/main/java/com/aizuda/easy/retry/server/common/client/RequestInterceptor.java new file mode 100644 index 00000000..31f552b9 --- /dev/null +++ b/easy-retry-server/easy-retry-server-common/src/main/java/com/aizuda/easy/retry/server/common/client/RequestInterceptor.java @@ -0,0 +1,45 @@ +package com.aizuda.easy.retry.server.common.client; + +import cn.hutool.core.util.StrUtil; +import lombok.extern.slf4j.Slf4j; +import okhttp3.Interceptor; +import okhttp3.Request; +import okhttp3.Response; +import org.jetbrains.annotations.NotNull; + +import java.io.IOException; +import java.util.concurrent.TimeUnit; + +/** + * @author: byteblogs168 + * @date : 2023-11-03 17:40 + * @since : 2.4.0 + */ +@Slf4j +public class RequestInterceptor implements Interceptor { + + public static final String TIMEOUT_TIME = "executorTimeout"; + + @NotNull + @Override + public Response intercept(@NotNull final Chain chain) throws IOException { + Request request = chain.request(); + String timeoutTime = request.header(TIMEOUT_TIME); + if (StrUtil.isNotBlank(timeoutTime)) { + int timeout = Integer.parseInt(timeoutTime); + log.info("url:[{}] timeout:[{}]", request.url(), timeout); + if (timeout <= 0) { + return chain.proceed(request); + } + + return chain + .withReadTimeout(timeout, TimeUnit.SECONDS) + .withConnectTimeout(timeout, TimeUnit.SECONDS) + .withWriteTimeout(timeout, TimeUnit.SECONDS) + .proceed(chain.request()); + } + + return chain.proceed(request); + + } +} diff --git a/easy-retry-server/easy-retry-server-common/src/main/java/com/aizuda/easy/retry/server/common/client/RpcClientInvokeHandler.java b/easy-retry-server/easy-retry-server-common/src/main/java/com/aizuda/easy/retry/server/common/client/RpcClientInvokeHandler.java index 87316ed5..dcf3d2b6 100644 --- a/easy-retry-server/easy-retry-server-common/src/main/java/com/aizuda/easy/retry/server/common/client/RpcClientInvokeHandler.java +++ b/easy-retry-server/easy-retry-server-common/src/main/java/com/aizuda/easy/retry/server/common/client/RpcClientInvokeHandler.java @@ -7,7 +7,6 @@ import com.aizuda.easy.retry.common.core.context.SpringContext; import com.aizuda.easy.retry.common.core.model.Result; import com.aizuda.easy.retry.common.core.util.HostUtils; import com.aizuda.easy.retry.common.core.util.JsonUtil; -import com.aizuda.easy.retry.server.common.allocate.client.ClientLoadBalanceManager.AllocationAlgorithmEnum; import com.aizuda.easy.retry.server.common.cache.CacheRegisterTable; import com.aizuda.easy.retry.server.common.client.annotation.Body; import com.aizuda.easy.retry.server.common.client.annotation.Header; @@ -22,7 +21,6 @@ import com.github.rholder.retry.Retryer; import com.github.rholder.retry.RetryerBuilder; import com.github.rholder.retry.StopStrategies; import com.github.rholder.retry.WaitStrategies; -import lombok.AllArgsConstructor; import lombok.Data; import lombok.extern.slf4j.Slf4j; import org.jetbrains.annotations.NotNull; @@ -30,7 +28,6 @@ import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.ResponseEntity; -import org.springframework.http.client.OkHttp3ClientHttpRequestFactory; import org.springframework.util.CollectionUtils; import org.springframework.web.client.ResourceAccessException; import org.springframework.web.client.RestClientException; @@ -70,11 +67,12 @@ public class RpcClientInvokeHandler implements InvocationHandler { private final boolean failover; private final Integer routeKey; private final String allocKey; + private final Integer executorTimeout; public RpcClientInvokeHandler(final String groupName, final RegisterNodeInfo registerNodeInfo, final boolean failRetry, final int retryTimes, final int retryInterval, final RetryListener retryListener, final Integer routeKey, final String allocKey, - final boolean failover) { + final boolean failover, final Integer executorTimeout) { this.groupName = groupName; this.hostId = registerNodeInfo.getHostId(); this.hostPort = registerNodeInfo.getHostPort(); @@ -87,6 +85,7 @@ public class RpcClientInvokeHandler implements InvocationHandler { this.failover = failover; this.routeKey = routeKey; this.allocKey = allocKey; + this.executorTimeout = executorTimeout; } @Override @@ -98,7 +97,7 @@ public class RpcClientInvokeHandler implements InvocationHandler { return doFailoverHandler(method, args, annotation); } - return requestRemote(method, args, annotation, 0); + return requestRemote(method, args, annotation, 1); } @NotNull @@ -136,6 +135,11 @@ public class RpcClientInvokeHandler implements InvocationHandler { Retryer retryer = buildResultRetryer(); + HttpHeaders requestHeaders = parasResult.requestHeaders; + if (Objects.nonNull(executorTimeout)) { + requestHeaders.set(RequestInterceptor.TIMEOUT_TIME, String.valueOf(executorTimeout)); + } + Result result = retryer.call(() -> { ResponseEntity response = restTemplate.exchange( // 拼接 url?a=1&b=1 diff --git a/easy-retry-server/easy-retry-server-common/src/main/java/com/aizuda/easy/retry/server/common/config/RestTemplateConfig.java b/easy-retry-server/easy-retry-server-common/src/main/java/com/aizuda/easy/retry/server/common/config/RestTemplateConfig.java index 900394b3..1048be2b 100644 --- a/easy-retry-server/easy-retry-server-common/src/main/java/com/aizuda/easy/retry/server/common/config/RestTemplateConfig.java +++ b/easy-retry-server/easy-retry-server-common/src/main/java/com/aizuda/easy/retry/server/common/config/RestTemplateConfig.java @@ -1,11 +1,16 @@ package com.aizuda.easy.retry.server.common.config; +import com.aizuda.easy.retry.server.common.client.RequestInterceptor; +import okhttp3.ConnectionPool; +import okhttp3.OkHttpClient; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.client.ClientHttpRequestFactory; import org.springframework.http.client.OkHttp3ClientHttpRequestFactory; import org.springframework.web.client.RestTemplate; +import java.util.concurrent.TimeUnit; + /** * @author: www.byteblogs.com * @date : 2022-03-09 14:19 @@ -14,19 +19,31 @@ import org.springframework.web.client.RestTemplate; public class RestTemplateConfig { @Bean - public RestTemplate restTemplate(ClientHttpRequestFactory factory){ + public RestTemplate restTemplate(ClientHttpRequestFactory factory) { return new RestTemplate(factory); } + @Bean - public ClientHttpRequestFactory okHttp3ClientHttpRequestFactory(){ - OkHttp3ClientHttpRequestFactory factory = new OkHttp3ClientHttpRequestFactory(); - factory.setReadTimeout(5000); - factory.setConnectTimeout(5000); - factory.setConnectTimeout(3000); - factory.setWriteTimeout(5000); - return factory; + public ClientHttpRequestFactory okHttp3ClientHttpRequestFactory() { + + OkHttpClient okHttpClient = new OkHttpClient.Builder() + // 整个流程耗费的超时时间 + .callTimeout(60, TimeUnit.SECONDS) + // 读取耗时 + .readTimeout(5000, TimeUnit.MILLISECONDS) + // 三次握手 + SSL建立耗时 + .connectTimeout(5000, TimeUnit.MILLISECONDS) + // 写入耗时 + .writeTimeout(5000, TimeUnit.MILLISECONDS) + // 当连接失败,尝试重连 + .retryOnConnectionFailure(true) + // 最大空闲连接数及连接的保活时间进行配置 + .connectionPool(new ConnectionPool(200, 5, TimeUnit.MINUTES)) + .addInterceptor(new RequestInterceptor()) + .build(); + + return new OkHttp3ClientHttpRequestFactory(okHttpClient); } - } diff --git a/easy-retry-server/easy-retry-server-retry-task/src/main/java/com/aizuda/easy/retry/server/retry/task/support/dispatch/actor/exec/ExecCallbackUnitActor.java b/easy-retry-server/easy-retry-server-retry-task/src/main/java/com/aizuda/easy/retry/server/retry/task/support/dispatch/actor/exec/ExecCallbackUnitActor.java index 6b3584f1..571c507a 100644 --- a/easy-retry-server/easy-retry-server-retry-task/src/main/java/com/aizuda/easy/retry/server/retry/task/support/dispatch/actor/exec/ExecCallbackUnitActor.java +++ b/easy-retry-server/easy-retry-server-retry-task/src/main/java/com/aizuda/easy/retry/server/retry/task/support/dispatch/actor/exec/ExecCallbackUnitActor.java @@ -145,6 +145,7 @@ public class ExecCallbackUnitActor extends AbstractActor { .failover(Boolean.TRUE) .routeKey(sceneConfig.getRouteKey()) .allocKey(sceneConfig.getSceneName()) + .executorTimeout(sceneConfig.getExecutorTimeout()) .client(RetryRpcClient.class) .build(); return rpcClient.callback(retryCallbackDTO); diff --git a/easy-retry-server/easy-retry-server-retry-task/src/main/java/com/aizuda/easy/retry/server/retry/task/support/dispatch/actor/exec/ExecUnitActor.java b/easy-retry-server/easy-retry-server-retry-task/src/main/java/com/aizuda/easy/retry/server/retry/task/support/dispatch/actor/exec/ExecUnitActor.java index 5cd11a28..bb81fa79 100644 --- a/easy-retry-server/easy-retry-server-retry-task/src/main/java/com/aizuda/easy/retry/server/retry/task/support/dispatch/actor/exec/ExecUnitActor.java +++ b/easy-retry-server/easy-retry-server-retry-task/src/main/java/com/aizuda/easy/retry/server/retry/task/support/dispatch/actor/exec/ExecUnitActor.java @@ -150,6 +150,7 @@ public class ExecUnitActor extends AbstractActor { .failover(Boolean.TRUE) .allocKey(retryTask.getSceneName()) .routeKey(sceneConfig.getRouteKey()) + .executorTimeout(sceneConfig.getExecutorTimeout()) .client(RetryRpcClient.class) .build(); diff --git a/easy-retry-server/easy-retry-server-web/src/main/java/com/aizuda/easy/retry/server/web/model/request/SceneConfigRequestVO.java b/easy-retry-server/easy-retry-server-web/src/main/java/com/aizuda/easy/retry/server/web/model/request/SceneConfigRequestVO.java index 12cc1d4b..f28959a8 100644 --- a/easy-retry-server/easy-retry-server-web/src/main/java/com/aizuda/easy/retry/server/web/model/request/SceneConfigRequestVO.java +++ b/easy-retry-server/easy-retry-server-web/src/main/java/com/aizuda/easy/retry/server/web/model/request/SceneConfigRequestVO.java @@ -50,8 +50,14 @@ public class SceneConfigRequestVO { */ @Max(message = "最大60000毫秒", value = SystemConstants.DEFAULT_DDL) @Min(message = "最小100ms", value = 100) + @NotNull(message = "调用链超时不能为空") private Long deadlineRequest; + @Max(message = "最大60(秒)", value = 60) + @Min(message = "最小1(秒)", value = 1) + @NotNull(message = "执行超时不能为空") + private Integer executorTimeout; + /** * 是否删除 */