From 510b651bcdcf92c5283477b9bdce1f93c64f8d02 Mon Sep 17 00:00:00 2001 From: byteblogs168 <598092184@qq.com> Date: Mon, 19 Jun 2023 23:00:35 +0800 Subject: [PATCH] =?UTF-8?q?feat:=202.0.0=201.=20=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E8=B0=83=E7=94=A8=E5=AE=A2=E6=88=B7=E7=AB=AF=E4=BB=A3=E7=90=86?= =?UTF-8?q?=E7=B1=BB=202.=20=E6=96=B0=E5=A2=9E=E4=B8=8B=E7=BA=BF=E8=B7=AF?= =?UTF-8?q?=E7=94=B1=E5=89=94=E9=99=A4=E5=8A=9F=E8=83=BD=203.=20=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E8=B7=AF=E7=94=B1=E8=BD=AC=E7=A7=BB=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../retry/server/client/RequestBuilder.java | 83 +++++++++ .../retry/server/client/RequestMethod.java | 16 ++ .../easy/retry/server/client/RpcClient.java | 27 +++ .../server/client/RpcClientInvokeHandler.java | 170 ++++++++++++++++++ .../retry/server/client/annotation/Body.java | 18 ++ .../server/client/annotation/Header.java | 18 ++ .../server/client/annotation/Mapping.java | 27 +++ .../retry/server/client/annotation/Param.java | 18 ++ .../actor/exec/ExecCallbackUnitActor.java | 30 ++-- .../dispatch/actor/exec/ExecUnitActor.java | 24 ++- 10 files changed, 409 insertions(+), 22 deletions(-) create mode 100644 easy-retry-server/src/main/java/com/aizuda/easy/retry/server/client/RequestBuilder.java create mode 100644 easy-retry-server/src/main/java/com/aizuda/easy/retry/server/client/RequestMethod.java create mode 100644 easy-retry-server/src/main/java/com/aizuda/easy/retry/server/client/RpcClient.java create mode 100644 easy-retry-server/src/main/java/com/aizuda/easy/retry/server/client/RpcClientInvokeHandler.java create mode 100644 easy-retry-server/src/main/java/com/aizuda/easy/retry/server/client/annotation/Body.java create mode 100644 easy-retry-server/src/main/java/com/aizuda/easy/retry/server/client/annotation/Header.java create mode 100644 easy-retry-server/src/main/java/com/aizuda/easy/retry/server/client/annotation/Mapping.java create mode 100644 easy-retry-server/src/main/java/com/aizuda/easy/retry/server/client/annotation/Param.java diff --git a/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/client/RequestBuilder.java b/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/client/RequestBuilder.java new file mode 100644 index 00000000..5a3d1c3a --- /dev/null +++ b/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/client/RequestBuilder.java @@ -0,0 +1,83 @@ +package com.aizuda.easy.retry.server.client; + + +import cn.hutool.core.lang.Assert; +import com.aizuda.easy.retry.server.exception.EasyRetryServerException; + +import java.lang.reflect.Proxy; +import java.util.Objects; + +/** + * 构建请求类型 + * + * @author: www.byteblogs.com + * @date : 2023-06-19 16:47 + * @since 2.0.0 + */ +public class RequestBuilder { + + private Class clintInterface; + private String groupName; + private String hostId; + private String hostIp; + private Integer hostPort; + private String contextPath; + + public static RequestBuilder newBuilder() { + return new RequestBuilder<>(); + } + + public RequestBuilder client(Class clintInterface) { + this.clintInterface = clintInterface; + return this; + } + + public RequestBuilder hostPort(Integer hostPort) { + this.hostPort = hostPort; + return this; + } + + public RequestBuilder contextPath(String contextPath) { + this.contextPath = contextPath; + return this; + } + + public RequestBuilder hostId(String hostId) { + this.hostId = hostId; + return this; + } + + public RequestBuilder hostIp(String hostIp) { + this.hostIp = hostIp; + return this; + } + + public RequestBuilder groupName(String groupName) { + this.groupName = groupName; + return this; + } + + public T build() { + if (Objects.isNull(clintInterface)) { + throw new EasyRetryServerException("clintInterface cannot be null"); + } + + Assert.notBlank(groupName, () -> new EasyRetryServerException("groupName cannot be null")); + Assert.notBlank(hostId, () -> new EasyRetryServerException("hostId cannot be null")); + Assert.notBlank(hostIp, () -> new EasyRetryServerException("hostIp cannot be null")); + Assert.notNull(hostPort, () -> new EasyRetryServerException("hostPort cannot be null")); + Assert.notBlank(contextPath, () -> new EasyRetryServerException("contextPath cannot be null")); + + try { + clintInterface = (Class) Class.forName(clintInterface.getName()); + } catch (Exception e) { + throw new EasyRetryServerException("class not found exception to: [{}]", clintInterface.getName()); + } + + RpcClientInvokeHandler clientInvokeHandler = new RpcClientInvokeHandler(groupName, hostId, hostIp, hostPort, contextPath); + + return (T) Proxy.newProxyInstance(clintInterface.getClassLoader(), + new Class[]{clintInterface}, clientInvokeHandler); + } + +} diff --git a/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/client/RequestMethod.java b/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/client/RequestMethod.java new file mode 100644 index 00000000..dd0256b5 --- /dev/null +++ b/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/client/RequestMethod.java @@ -0,0 +1,16 @@ +package com.aizuda.easy.retry.server.client; + +/** + * 请求类型 + * + * @author: www.byteblogs.com + * @date : 2023-06-19 08:53 + * @since 2.0.0 + */ +public enum RequestMethod { + GET, + POST; + + RequestMethod() { + } +} diff --git a/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/client/RpcClient.java b/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/client/RpcClient.java new file mode 100644 index 00000000..20292cd5 --- /dev/null +++ b/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/client/RpcClient.java @@ -0,0 +1,27 @@ +package com.aizuda.easy.retry.server.client; + +import com.aizuda.easy.retry.client.model.DispatchRetryDTO; +import com.aizuda.easy.retry.client.model.DispatchRetryResultDTO; +import com.aizuda.easy.retry.client.model.RetryCallbackDTO; +import com.aizuda.easy.retry.common.core.model.EasyRetryHeaders; +import com.aizuda.easy.retry.common.core.model.Result; +import com.aizuda.easy.retry.server.client.annotation.Body; +import com.aizuda.easy.retry.server.client.annotation.Header; +import com.aizuda.easy.retry.server.client.annotation.Mapping; + +/** + * 调用客户端接口 + * + * @author: www.byteblogs.com + * @date : 2023-06-19 15:40 + * @since 2.0.0 + */ +public interface RpcClient { + + @Mapping(path = "/retry/dispatch/v1", method = RequestMethod.POST) + Result dispatch(@Body DispatchRetryDTO dispatchRetryDTO, @Header EasyRetryHeaders headers); + + @Mapping(path = "/retry/callback/v1", method = RequestMethod.POST) + Result callback(@Body RetryCallbackDTO retryCallbackDTO); + +} diff --git a/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/client/RpcClientInvokeHandler.java b/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/client/RpcClientInvokeHandler.java new file mode 100644 index 00000000..e5679b23 --- /dev/null +++ b/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/client/RpcClientInvokeHandler.java @@ -0,0 +1,170 @@ +package com.aizuda.easy.retry.server.client; + +import cn.hutool.core.lang.Assert; +import cn.hutool.core.util.URLUtil; +import com.aizuda.easy.retry.common.core.constant.SystemConstants; +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.JsonUtil; +import com.aizuda.easy.retry.server.client.annotation.Body; +import com.aizuda.easy.retry.server.client.annotation.Header; +import com.aizuda.easy.retry.server.client.annotation.Mapping; +import com.aizuda.easy.retry.server.client.annotation.Param; +import com.aizuda.easy.retry.server.dto.RegisterNodeInfo; +import com.aizuda.easy.retry.server.exception.EasyRetryServerException; +import com.aizuda.easy.retry.server.support.cache.CacheRegisterTable; +import com.aizuda.easy.retry.server.support.handler.ClientNodeAllocateHandler; +import lombok.extern.slf4j.Slf4j; +import org.jetbrains.annotations.NotNull; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; +import org.springframework.util.CollectionUtils; +import org.springframework.web.client.ResourceAccessException; +import org.springframework.web.client.RestClientException; +import org.springframework.web.client.RestTemplate; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Parameter; +import java.text.MessageFormat; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.Set; + +/** + * 请求处理器 + * + * @author: www.byteblogs.com + * @date : 2023-05-11 21:45 + * @since 2.0.0 + */ +@Slf4j +public class RpcClientInvokeHandler implements InvocationHandler { + + public static final String URL = "http://{0}:{1}/{2}"; + + private final String groupName; + private String hostId; + private String hostIp; + private Integer hostPort; + private String contextPath; + + public RpcClientInvokeHandler( + final String groupName, + final String hostId, + final String hostIp, + final Integer hostPort, + final String contextPath) { + this.groupName = groupName; + this.hostId = hostId; + this.hostIp = hostIp; + this.hostPort = hostPort; + this.contextPath = contextPath; + } + + @Override + public Result invoke(final Object proxy, final Method method, final Object[] args) throws Throwable { + Mapping annotation = method.getAnnotation(Mapping.class); + Assert.notNull(annotation, () -> new EasyRetryServerException("@Mapping cannot be null")); + + Set serverNodeSet = CacheRegisterTable.getServerNodeSet(groupName); + // 最多调用size次 + int size = serverNodeSet.size(); + for (int count = 1; count <= size; count++) { + log.info("Start request client. count:[{}] hostId:[{}] addr:[{}:{}]", count, hostId, hostIp, hostPort); + Result result = requestRemote(method, args, annotation, count); + if (Objects.nonNull(result)) { + return result; + } + } + + throw new EasyRetryServerException("No available nodes."); + } + + private Result requestRemote(Method method, Object[] args, Mapping mapping, int count) { + + try { + Object body = null; + HttpHeaders requestHeaders = new HttpHeaders(); + Map paramMap = new HashMap<>(); + // 解析参数 + Parameter[] parameters = method.getParameters(); + for (int i = 0; i < parameters.length; i++) { + Parameter parameter = parameters[i]; + if (parameter.isAnnotationPresent(Body.class)) { + body = args[i]; + } else if ((parameter.isAnnotationPresent(Header.class))) { + requestHeaders.add(SystemConstants.EASY_RETRY_HEAD_KEY, JsonUtil.toJsonString(args[i])); + } else if ((parameter.isAnnotationPresent(Param.class))) { + paramMap.put(parameter.getAnnotation(Param.class).name(), args[i]); + } else { + throw new EasyRetryServerException("parameter error"); + } + } + + // 若是POST请求,请求体不能是null + if (RequestMethod.POST.name().equals(mapping.method().name())) { + Assert.notNull(body, () -> new EasyRetryServerException("body cannot be null")); + } + + // 拼接 url?a=1&b=1 + RestTemplate restTemplate = SpringContext.CONTEXT.getBean(RestTemplate.class); + ResponseEntity response = restTemplate.exchange( + getUrl(mapping, paramMap).toString(), + HttpMethod.valueOf(mapping.method().name()), + new HttpEntity<>(body, requestHeaders), + Result.class); + + log.info("Request client success. count:[{}] hostId:[{}] addr:[{}:{}]", count, hostId, hostIp, hostPort); + + return Objects.requireNonNull(response.getBody()); + } catch (RestClientException ex) { + // 网络异常 + if (ex instanceof ResourceAccessException) { + log.error("request client I/O error, count:[{}] hostId:[{}] addr:[{}:{}]", count, hostId, hostIp, hostPort, ex); + + // 进行路由剔除处理 + CacheRegisterTable.remove(groupName, hostId); + // 重新选一个可用的客户端节点 + ClientNodeAllocateHandler clientNodeAllocateHandler = SpringContext.CONTEXT.getBean( + ClientNodeAllocateHandler.class); + RegisterNodeInfo serverNode = clientNodeAllocateHandler.getServerNode(groupName); + // 这里表示无可用节点 + if (Objects.isNull(serverNode)) { + throw ex; + } + + this.hostId = serverNode.getHostId(); + this.hostPort = serverNode.getHostPort(); + this.hostIp = serverNode.getHostIp(); + this.contextPath = serverNode.getContextPath(); + + } else { + // 其他异常继续抛出 + log.error("request client error.count:[{}] hostId:[{}] addr:[{}:{}]", count, hostId, hostIp, hostPort, ex); + throw ex; + } + } catch (Exception ex) { + log.error("request client unknown exception. count:[{}] hostId:[{}] addr:[{}:{}]", count, hostId, hostIp, hostPort, ex); + throw ex; + } + + return null; + } + + @NotNull + private StringBuilder getUrl(Mapping mapping, Map paramMap) { + StringBuilder url = new StringBuilder(MessageFormat.format(URL, hostIp, hostPort.toString(), contextPath)); + url.append(mapping.path()); + if (!CollectionUtils.isEmpty(paramMap)) { + String query = URLUtil.buildQuery(paramMap, null); + url.append("?").append(query); + } + + return url; + } + +} diff --git a/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/client/annotation/Body.java b/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/client/annotation/Body.java new file mode 100644 index 00000000..d7e32ba8 --- /dev/null +++ b/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/client/annotation/Body.java @@ -0,0 +1,18 @@ +package com.aizuda.easy.retry.server.client.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * @author: shuguang.zhang + * @date : 2023-06-19 16:02 + */ +@Target({ElementType.PARAMETER}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface Body { + +} diff --git a/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/client/annotation/Header.java b/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/client/annotation/Header.java new file mode 100644 index 00000000..e33056ae --- /dev/null +++ b/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/client/annotation/Header.java @@ -0,0 +1,18 @@ +package com.aizuda.easy.retry.server.client.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * @author: shuguang.zhang + * @date : 2023-06-19 16:02 + */ +@Target({ElementType.PARAMETER}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface Header { + +} diff --git a/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/client/annotation/Mapping.java b/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/client/annotation/Mapping.java new file mode 100644 index 00000000..9110d6d8 --- /dev/null +++ b/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/client/annotation/Mapping.java @@ -0,0 +1,27 @@ +package com.aizuda.easy.retry.server.client.annotation; + +import com.aizuda.easy.retry.server.client.RequestMethod; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 接口定义 + * + * @author: www.byteblogs.com + * @date : 2023-05-11 22:32 + * @since 1.3.0 + */ +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface Mapping { + + RequestMethod method() default RequestMethod.GET; + + String path() default ""; + +} diff --git a/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/client/annotation/Param.java b/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/client/annotation/Param.java new file mode 100644 index 00000000..15bd1067 --- /dev/null +++ b/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/client/annotation/Param.java @@ -0,0 +1,18 @@ +package com.aizuda.easy.retry.server.client.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * @author: shuguang.zhang + * @date : 2023-06-19 16:10 + */ +@Target({ElementType.PARAMETER}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface Param { + String name(); +} diff --git a/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/support/dispatch/actor/exec/ExecCallbackUnitActor.java b/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/support/dispatch/actor/exec/ExecCallbackUnitActor.java index 19d69c39..dea29ac1 100644 --- a/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/support/dispatch/actor/exec/ExecCallbackUnitActor.java +++ b/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/support/dispatch/actor/exec/ExecCallbackUnitActor.java @@ -3,12 +3,12 @@ package com.aizuda.easy.retry.server.support.dispatch.actor.exec; import akka.actor.AbstractActor; import akka.actor.ActorRef; import com.aizuda.easy.retry.client.model.RetryCallbackDTO; -import com.aizuda.easy.retry.common.core.constant.SystemConstants; import com.aizuda.easy.retry.server.akka.ActorGenerator; +import com.aizuda.easy.retry.server.client.RequestBuilder; +import com.aizuda.easy.retry.server.client.RpcClient; import com.aizuda.easy.retry.server.dto.RegisterNodeInfo; import com.aizuda.easy.retry.server.enums.StatusEnum; import com.aizuda.easy.retry.common.core.log.LogUtils; -import com.aizuda.easy.retry.common.core.model.EasyRetryHeaders; import com.aizuda.easy.retry.common.core.model.Result; import com.aizuda.easy.retry.common.core.util.JsonUtil; import com.aizuda.easy.retry.server.persistence.mybatis.po.RetryTask; @@ -22,12 +22,9 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.context.annotation.Scope; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpHeaders; import org.springframework.stereotype.Component; import org.springframework.web.client.RestTemplate; -import java.text.MessageFormat; import java.util.Objects; import java.util.concurrent.Callable; @@ -49,8 +46,6 @@ public class ExecCallbackUnitActor extends AbstractActor { @Autowired @Qualifier("bitSetIdempotentStrategyHandler") private IdempotentStrategy idempotentStrategy; - @Autowired - private RestTemplate restTemplate; @Override public Receive createReceive() { @@ -109,7 +104,7 @@ public class ExecCallbackUnitActor extends AbstractActor { * @param retryTask {@link RetryTask} 需要重试的数据 * @return 重试结果返回值 */ - private Result callClient(RetryTask retryTask, RegisterNodeInfo serverNode) { + private Result callClient(RetryTask retryTask, RegisterNodeInfo serverNode) { // 回调参数 RetryCallbackDTO retryCallbackDTO = new RetryCallbackDTO(); @@ -121,13 +116,22 @@ public class ExecCallbackUnitActor extends AbstractActor { retryCallbackDTO.setExecutorName(retryTask.getExecutorName()); retryCallbackDTO.setUniqueId(retryTask.getUniqueId()); - HttpEntity requestEntity = new HttpEntity<>(retryCallbackDTO); +// HttpEntity requestEntity = new HttpEntity<>(retryCallbackDTO); +// +// String format = MessageFormat.format(URL, serverNode.getHostIp(), serverNode.getHostPort().toString(), serverNode.getContextPath()); +// Result result = restTemplate.postForObject(format, requestEntity, Result.class); - String format = MessageFormat.format(URL, serverNode.getHostIp(), serverNode.getHostPort().toString(), serverNode.getContextPath()); - Result result = restTemplate.postForObject(format, requestEntity, Result.class); - LogUtils.info(log, "请求客户端 format:[{}] response:[{}}] ", format, JsonUtil.toJsonString(result)); - return result; + RpcClient rpcClient = RequestBuilder.newBuilder() + .hostPort(serverNode.getHostPort()) + .groupName(serverNode.getGroupName()) + .hostId(serverNode.getHostId()) + .hostIp(serverNode.getHostIp()) + .contextPath(serverNode.getContextPath()) + .client(RpcClient.class) + .build(); + + return rpcClient.callback(retryCallbackDTO); } diff --git a/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/support/dispatch/actor/exec/ExecUnitActor.java b/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/support/dispatch/actor/exec/ExecUnitActor.java index 112af28b..f933780b 100644 --- a/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/support/dispatch/actor/exec/ExecUnitActor.java +++ b/easy-retry-server/src/main/java/com/aizuda/easy/retry/server/support/dispatch/actor/exec/ExecUnitActor.java @@ -10,6 +10,8 @@ import com.aizuda.easy.retry.common.core.model.EasyRetryHeaders; import com.aizuda.easy.retry.common.core.model.Result; import com.aizuda.easy.retry.common.core.util.JsonUtil; import com.aizuda.easy.retry.server.akka.ActorGenerator; +import com.aizuda.easy.retry.server.client.RequestBuilder; +import com.aizuda.easy.retry.server.client.RpcClient; import com.aizuda.easy.retry.server.enums.StatusEnum; import com.aizuda.easy.retry.server.dto.RegisterNodeInfo; import com.aizuda.easy.retry.server.persistence.mybatis.po.RetryTask; @@ -50,8 +52,6 @@ public class ExecUnitActor extends AbstractActor { @Autowired @Qualifier("bitSetIdempotentStrategyHandler") private IdempotentStrategy idempotentStrategy; - @Autowired - private RestTemplate restTemplate; @Override public Receive createReceive() { @@ -137,14 +137,20 @@ public class ExecUnitActor extends AbstractActor { easyRetryHeaders.setEasyRetryId(retryTask.getUniqueId()); requestHeaders.add(SystemConstants.EASY_RETRY_HEAD_KEY, JsonUtil.toJsonString(easyRetryHeaders)); - HttpEntity requestEntity = new HttpEntity<>(dispatchRetryDTO, requestHeaders); - - String format = MessageFormat.format(URL, serverNode.getHostIp(), serverNode.getHostPort().toString(), serverNode.getContextPath()); - Result result = restTemplate.postForObject(format, requestEntity, Result.class); - - LogUtils.info(log, "请求客户端 format:[{}] response:[{}}] ", format, JsonUtil.toJsonString(result)); - return result; + RpcClient rpcClient = RequestBuilder.newBuilder() + .hostPort(serverNode.getHostPort()) + .groupName(serverNode.getGroupName()) + .hostId(serverNode.getHostId()) + .hostIp(serverNode.getHostIp()) + .contextPath(serverNode.getContextPath()) + .client(RpcClient.class) + .build(); +// HttpEntity requestEntity = new HttpEntity<>(dispatchRetryDTO, requestHeaders); +// +// String format = MessageFormat.format(URL, serverNode.getHostIp(), serverNode.getHostPort().toString(), serverNode.getContextPath()); +// Result result = restTemplate.postForObject(format, requestEntity, Result.class); + return rpcClient.dispatch(dispatchRetryDTO, easyRetryHeaders); }