从零开始手写 dubbo rpc 框架

您所在的位置:网站首页 dubbo失败重试 从零开始手写 dubbo rpc 框架

从零开始手写 dubbo rpc 框架

2024-07-12 17:46| 来源: 网络整理| 查看: 265

fail 失败策略 说明

当我们调用服务失败的时候,有很多策略。

比如:

FailFast

快速失败

FailOver

尝试下一次调用

等等其他各种策略。

实现思路

不同的失败策略方式只是处理失败的方式不同而已。

这个主要放在客户端,当调用失败的时候,重新进行尝试即可。

代码实现 失败策略接口 /** * 失败策略 * @author binbin.hou * @since 0.1.1 */ public interface FailStrategy { /** * 失败策略 * @param context 远程调用上下文 * @return 最终的结果值 * @since 0.1.1 */ Object fail(final RemoteInvokeContext context); } FailOver 策略

主要展示下这个策略,其他的类似。

这里是默认失败后重试两次,因为 rpc 和 mq 有些不同。

一般调用都有超时的限制,不适合重试太多次。

/** * 如果调用遇到异常,则进行尝试其他 server 端进行调用。 * (1)最大重试次数=2 不能太多次 * (2)重试的时候如何标识重试次数还剩多少次? * (3)如何在失败的时候获取重试相关上下文? * * @author binbin.hou * @since 0.1.1 */ @ThreadSafe class FailOverStrategy implements FailStrategy { @Override public Object fail(final RemoteInvokeContext context) { try { final Class returnType = context.request().returnType(); final RpcResponse rpcResponse = context.rpcResponse(); return RpcResponses.getResult(rpcResponse, returnType); } catch (Exception e) { Throwable throwable = e.getCause(); if(throwable instanceof RpcTimeoutException) { throw new RpcRuntimeException(); } // 进行失败重试。 int retryTimes = context.retryTimes(); if(retryTimes > 0) { // 进行重试 retryTimes--; context.retryTimes(retryTimes); return context.remoteInvokeService() .remoteInvoke(context); } else { throw e; } } } } 测试代码 注册中心

启动

服务端 server1

正常服务启动

server2

启动异常服务,实现如下:

public class CalculatorServiceErrorImpl implements CalculatorService { public CalculateResponse sum(CalculateRequest request) { throw new RuntimeException("服务端异常"); } } 客户端 测试代码 public static void main(String[] args) { // 服务配置信息 ReferenceConfig config = ClientBs.newInstance(); config.serviceId(ServiceIdConst.CALC); config.serviceInterface(CalculatorService.class); // 自动发现服务 config.subscribe(true); config.registerCenter(ServiceIdConst.REGISTER_CENTER); CalculatorService calculatorService = config.reference(); CalculateRequest request = new CalculateRequest(); request.setOne(10); request.setTwo(20); // 循环 1 次,验证 fail-over CalculateResponse response = calculatorService.sum(request); System.out.println(response); } 测试日志

这里重试了2次,可以通过日志 [Client] start call remote with request 观察到。

[INFO] [2019-11-01 22:29:52.848] [main] [c.g.h.r.c.p.i.RemoteInvokeServiceImpl.remoteInvoke] - [Client] start call channel id: 502b73fffec4485c-00001ea0-00000001-d5e67f0043cf621c-70d8b9e8 [INFO] [2019-11-01 22:29:52.853] [main] [c.g.h.r.c.p.i.RemoteInvokeServiceImpl.remoteInvoke] - [Client] start call remote with request: DefaultRpcRequest{seqId='8c71aa3a1dfd4d0d8d6b7f5c82a3c119', createTime=1572618592829, serviceId='calc', methodName='sum', paramTypeNames=[com.github.houbb.rpc.server.facade.model.CalculateRequest], paramValues=[CalculateRequest{one=10, two=20}], returnType=class com.github.houbb.rpc.server.facade.model.CalculateResponse} [INFO] [2019-11-01 22:29:52.854] [main] [c.g.h.r.c.i.i.DefaultInvokeService.addRequest] - [Client] start add request for seqId: 8c71aa3a1dfd4d0d8d6b7f5c82a3c119, timeoutMills: 60000 [INFO] [2019-11-01 22:29:52.856] [main] [c.g.h.r.c.i.i.DefaultInvokeService.getResponse] - [Client] seq 8c71aa3a1dfd4d0d8d6b7f5c82a3c119 对应结果为空,进入等待 [INFO] [2019-11-01 22:29:52.869] [nioEventLoopGroup-4-1] [c.g.h.r.c.i.i.DefaultInvokeService.addResponse] - [Client] 获取结果信息,seqId: 8c71aa3a1dfd4d0d8d6b7f5c82a3c119, rpcResponse: DefaultRpcResponse{seqId='8c71aa3a1dfd4d0d8d6b7f5c82a3c119', error=com.github.houbb.rpc.common.exception.RpcRuntimeException: java.lang.reflect.InvocationTargetException, result=null} [INFO] [2019-11-01 22:29:52.870] [nioEventLoopGroup-4-1] [c.g.h.r.c.i.i.DefaultInvokeService.addResponse] - [Client] seqId:8c71aa3a1dfd4d0d8d6b7f5c82a3c119 信息已经放入,通知所有等待方 [INFO] [2019-11-01 22:29:52.870] [nioEventLoopGroup-4-1] [c.g.h.r.c.i.i.DefaultInvokeService.addResponse] - [Client] seqId:8c71aa3a1dfd4d0d8d6b7f5c82a3c119 remove from request map [INFO] [2019-11-01 22:29:52.871] [nioEventLoopGroup-4-1] [c.g.h.r.c.h.RpcClientHandler.channelRead0] - [Client] response is :DefaultRpcResponse{seqId='8c71aa3a1dfd4d0d8d6b7f5c82a3c119', error=com.github.houbb.rpc.common.exception.RpcRuntimeException: java.lang.reflect.InvocationTargetException, result=null} [INFO] [2019-11-01 22:29:52.871] [main] [c.g.h.r.c.i.i.DefaultInvokeService.getResponse] - [Client] seq 8c71aa3a1dfd4d0d8d6b7f5c82a3c119 对应结果已经获取: DefaultRpcResponse{seqId='8c71aa3a1dfd4d0d8d6b7f5c82a3c119', error=com.github.houbb.rpc.common.exception.RpcRuntimeException: java.lang.reflect.InvocationTargetException, result=null} [INFO] [2019-11-01 22:29:52.873] [main] [c.g.h.r.c.p.i.RemoteInvokeServiceImpl.remoteInvoke] - [Client] start call channel id: 502b73fffec4485c-00001ea0-00000001-d5e67f0043cf621c-70d8b9e8 [INFO] [2019-11-01 22:29:52.875] [main] [c.g.h.r.c.p.i.RemoteInvokeServiceImpl.remoteInvoke] - [Client] start call remote with request: DefaultRpcRequest{seqId='048d0b5a5db24233abffd80bed6513c4', createTime=1572618592829, serviceId='calc', methodName='sum', paramTypeNames=[com.github.houbb.rpc.server.facade.model.CalculateRequest], paramValues=[CalculateRequest{one=10, two=20}], returnType=class com.github.houbb.rpc.server.facade.model.CalculateResponse} [INFO] [2019-11-01 22:29:52.875] [main] [c.g.h.r.c.i.i.DefaultInvokeService.addRequest] - [Client] start add request for seqId: 048d0b5a5db24233abffd80bed6513c4, timeoutMills: 60000 [INFO] [2019-11-01 22:29:52.876] [main] [c.g.h.r.c.i.i.DefaultInvokeService.getResponse] - [Client] seq 048d0b5a5db24233abffd80bed6513c4 对应结果为空,进入等待 [INFO] [2019-11-01 22:29:52.884] [nioEventLoopGroup-4-1] [c.g.h.r.c.i.i.DefaultInvokeService.addResponse] - [Client] 获取结果信息,seqId: 048d0b5a5db24233abffd80bed6513c4, rpcResponse: DefaultRpcResponse{seqId='048d0b5a5db24233abffd80bed6513c4', error=com.github.houbb.rpc.common.exception.RpcRuntimeException: java.lang.reflect.InvocationTargetException, result=null} [INFO] [2019-11-01 22:29:52.885] [nioEventLoopGroup-4-1] [c.g.h.r.c.i.i.DefaultInvokeService.addResponse] - [Client] seqId:048d0b5a5db24233abffd80bed6513c4 信息已经放入,通知所有等待方 [INFO] [2019-11-01 22:29:52.885] [nioEventLoopGroup-4-1] [c.g.h.r.c.i.i.DefaultInvokeService.addResponse] - [Client] seqId:048d0b5a5db24233abffd80bed6513c4 remove from request map [INFO] [2019-11-01 22:29:52.886] [nioEventLoopGroup-4-1] [c.g.h.r.c.h.RpcClientHandler.channelRead0] - [Client] response is :DefaultRpcResponse{seqId='048d0b5a5db24233abffd80bed6513c4', error=com.github.houbb.rpc.common.exception.RpcRuntimeException: java.lang.reflect.InvocationTargetException, result=null} [INFO] [2019-11-01 22:29:52.886] [main] [c.g.h.r.c.i.i.DefaultInvokeService.getResponse] - [Client] seq 048d0b5a5db24233abffd80bed6513c4 对应结果已经获取: DefaultRpcResponse{seqId='048d0b5a5db24233abffd80bed6513c4', error=com.github.houbb.rpc.common.exception.RpcRuntimeException: java.lang.reflect.InvocationTargetException, result=null} [INFO] [2019-11-01 22:29:52.886] [main] [c.g.h.r.c.p.i.RemoteInvokeServiceImpl.remoteInvoke] - [Client] start call channel id: 502b73fffec4485c-00001ea0-00000001-d5e67f0043cf621c-70d8b9e8 [INFO] [2019-11-01 22:29:52.887] [main] [c.g.h.r.c.p.i.RemoteInvokeServiceImpl.remoteInvoke] - [Client] start call remote with request: DefaultRpcRequest{seqId='8c6002afa9c4471a8d2f6c46f2efd8e0', createTime=1572618592829, serviceId='calc', methodName='sum', paramTypeNames=[com.github.houbb.rpc.server.facade.model.CalculateRequest], paramValues=[CalculateRequest{one=10, two=20}], returnType=class com.github.houbb.rpc.server.facade.model.CalculateResponse} [INFO] [2019-11-01 22:29:52.888] [main] [c.g.h.r.c.i.i.DefaultInvokeService.addRequest] - [Client] start add request for seqId: 8c6002afa9c4471a8d2f6c46f2efd8e0, timeoutMills: 60000 [INFO] [2019-11-01 22:29:52.888] [main] [c.g.h.r.c.i.i.DefaultInvokeService.getResponse] - [Client] seq 8c6002afa9c4471a8d2f6c46f2efd8e0 对应结果为空,进入等待 [INFO] [2019-11-01 22:29:52.896] [nioEventLoopGroup-4-1] [c.g.h.r.c.i.i.DefaultInvokeService.addResponse] - [Client] 获取结果信息,seqId: 8c6002afa9c4471a8d2f6c46f2efd8e0, rpcResponse: DefaultRpcResponse{seqId='8c6002afa9c4471a8d2f6c46f2efd8e0', error=com.github.houbb.rpc.common.exception.RpcRuntimeException: java.lang.reflect.InvocationTargetException, result=null} [INFO] [2019-11-01 22:29:52.897] [nioEventLoopGroup-4-1] [c.g.h.r.c.i.i.DefaultInvokeService.addResponse] - [Client] seqId:8c6002afa9c4471a8d2f6c46f2efd8e0 信息已经放入,通知所有等待方 [INFO] [2019-11-01 22:29:52.897] [nioEventLoopGroup-4-1] [c.g.h.r.c.i.i.DefaultInvokeService.addResponse] - [Client] seqId:8c6002afa9c4471a8d2f6c46f2efd8e0 remove from request map [INFO] [2019-11-01 22:29:52.897] [nioEventLoopGroup-4-1] [c.g.h.r.c.h.RpcClientHandler.channelRead0] - [Client] response is :DefaultRpcResponse{seqId='8c6002afa9c4471a8d2f6c46f2efd8e0', error=com.github.houbb.rpc.common.exception.RpcRuntimeException: java.lang.reflect.InvocationTargetException, result=null} [INFO] [2019-11-01 22:29:52.898] [main] [c.g.h.r.c.i.i.DefaultInvokeService.getResponse] - [Client] seq 8c6002afa9c4471a8d2f6c46f2efd8e0 对应结果已经获取: DefaultRpcResponse{seqId='8c6002afa9c4471a8d2f6c46f2efd8e0', error=com.github.houbb.rpc.common.exception.RpcRuntimeException: java.lang.reflect.InvocationTargetException, result=null} Exception in thread "main" com.github.houbb.rpc.common.exception.RpcRuntimeException: com.github.houbb.rpc.common.exception.RpcRuntimeException: java.lang.reflect.InvocationTargetException 可以改进的地方 失败的服务端处理

因为我这边默认实现是 random,可能会出现多次随机到同一台服务器的情况。

还有就是如果调用一次出现异常,应该把这个异常的服务器,暂时移除。

等待后期心跳重新连接。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3