rpc框架简易实现

dubbo,作为一个成熟、易用、多支持的远程方法调用框架,应用广泛。为了透彻理解dubbo,我们今天来实现一把自己的dubbo。

分析

为了实现dubbo,我们需要做哪些事情呢?

  1. 远程,必然涉及到网络通信,这个我们用成熟的netty框架来做
  2. 方法调用转为网络请求,客户端的方法调用,可以通过aop将行为转为网络请求。
    那么,网络请求要做哪些事情呢?要调用远程方法,这就意味着服务端需要知道调用的类、方法以及方法参数值。
    所以我们封装了一个远程调用信息类来进行交互:RpcInfo(还有表示返回结果的result、success、exception等属性),在进行网络通信时,数据通过Kryo的方式序列化(因为它占用空间少、速度快,但是它要求序列化的类必须有无参的构造方法)
  3. 方法调用与响应结果反馈是不同的线程,如何拿到返回结果数据。
    这里需要一个通讯机制,本项目采用简单的方式,应用中维护一个map,在发送前,生成id作为key,然后将调用信息对象放入到map中,接着通过该调用信息对象wait,阻塞。在调用结果返回时,调用的线程就会被唤醒,根据最新的返回结果来给方法调用者反馈。

实现步骤

1、netty框架

首先客户端与服务端的netty使用代码
服务端:
在这里插入图片描述

客户端:
在这里插入图片描述

2、触发网络请求

方法调用转化为网络请求,此处不做aop实现,采用直接调用的形式(也就是aop拦截器中会做的事情)
在这里插入图片描述

3、错误信息反馈

如果从invoke开始直到拿到结果的过程中出错,怎么提示给客户端?我们将错误信息封装到RpcInfo中,在出现异常的时候,就将该对象写入到结果中。
在这里插入图片描述

4、异常信息的唯一请求id

但是netty的exceptionCaught方法是没有数据信息参数的,在返回异常信息的时候标示客户端请求的唯一id拿不到,怎么办?

很容易想到的一种方案是在服务端读到id信息之后就写入threadLocal中,之后exceptionCaught方法中从threadLocal取就好,笔者一开始也是这么想的,但是后来发现netty的handler链路不一定是在一个线程中:
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

所以需要加上对同一个请求handler链路跨越多个线程的支持,笔者的实现方案是在channelRead,write前后都加上try catch,这样就不会走到exceptionCaught中。

想到rpc实现比如dubbo可以增加许多用户自定义filter,也为了方便通过handler给本rpc实现添加更多的特征,将这部分代码进行了抽取,提取出一个ChannelHandlerAdapter基类,本实现中用到的ChannelHandlerAdapter都继承该基类(读取在反序列化之前,写操作在序列化之后的除外)。
在这里插入图片描述

在这里插入图片描述

5、客户端与服务端handler

接下来的就比较好理解了
客户端的handler
在这里插入图片描述

服务端端handler
在这里插入图片描述

6、序列化的handler

在这里插入图片描述

代码详见:https://github.com/guzhangyu/practice-Code/tree/master/src/main/java/com/phei/netty/rpc

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
介绍RCP的实现原理 目录 1. 前言 2 2. 基本概念 3 2.1. IDL 3 2.2. 代理(Proxy) 3 2.3. 存根(Stub) 4 3. 三要素 4 3.1. 网络通讯 4 3.2. 消息编解码 5 3.3. IDL编译器 5 4. flex和bison 5 4.1. 准备概念 5 4.1.1. 正则表达式(regex/regexp) 6 4.1.2. 符号∈ 6 4.1.3. 终结符/非终结符/产生式 6 4.1.4. 记号(Token) 6 4.1.5. 形式文法 7 4.1.6. 上下文无关文法(CFG) 7 4.1.7. BNF 8 4.1.8. 推导 8 4.1.9. 语法树 8 4.1.10. LL(k) 9 4.1.11. LR(k) 9 4.1.12. LALR(k) 9 4.1.13. GLR 9 4.1.14. 移进/归约 9 4.2. flex和bison文件格式 9 4.2.1. 定义部分 10 4.2.2. 规则部分 10 4.2.3. 用户子例程部分 10 4.3. flex基础 10 4.3.1. flex文件格式 11 4.3.2. 选项 11 4.3.3. 名字定义 11 4.3.4. 词法规则 12 4.3.5. 匹配规则 12 4.3.6. %option 13 4.3.7. 全局变量yytext 13 4.3.8. 全局变量yyval 13 4.3.9. 全局变量yyleng 13 4.3.10. 全局函数yylex 13 4.3.11. 全局函数yywrap 13 4.4. bison基础 14 4.4.1. bison文件格式 14 4.4.2. %union 14 4.4.3. %token 15 4.4.4. 全局函数yyerror() 15 4.4.5. 全局函数yyparse() 15 4.5. 例1:单词计数 15 4.5.1. 目的 15 4.5.2. flex词法文件wc.l 16 4.5.3. Makefile 16 4.6. 例2:表达式 17 4.6.1. 目的 17 4.6.2. flex词法exp.l 17 4.6.3. bison语法exp.y 17 4.6.4. Makefile 19 4.6.5. 代码集成 19 4.7. 例3:函数 20 4.7.1. 目的 20 4.7.2. func.h 20 4.7.3. func.c 21 4.7.4. IDL代码func.idl 22 4.7.5. flex词法func.l 22 4.7.6. bison语法func.y 24 4.7.7. Makefile 27 5. 进阶 27 5.1. 客户端函数实现 27 5.2. 服务端函数实现 28 5.2.1. Stub部分实现 28 5.2.2. 用户部分实现 29 6. 参考资料 29

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值