请选择 进入手机版 | 继续访问电脑版

基于Netty的RPC框架

[复制链接]
谢世民 发表于 2021-1-1 18:31:48 | 显示全部楼层 |阅读模式 打印 上一主题 下一主题
概述

RPC(Remote Procedure Call),远程过程调用,是一个盘算机通信协议,该协议允许运行一个进程调用另一个进程,而程序员无需额外为这个交互作用编程。
两个大概多个应用程序分布在差别的服务器上,他们之间的调用在客户端看来,就跟调用当地方法一样。
场景的RPC框架用阿里的dubbo、Google的gRPC,Apache的thrift、spring 的SpringCloud等。
调用流程:

clientsub是客户端当地调用的署理,ServerSub是服务端的署理。
流程表明:

  • 服务消费端当地调用方式来调用远程服务。
  • ClientSub吸收到调用后,负责将方法,参数等,封装成可以或许进行网络传输的消息体。
  • ClientSub将消息进行编码后发送到服务端。
  • 服务端的ServerSub吸收到消息后对消息进行解码。
  • 找到服务器当地的对应服务进行调用,并把返回值返回给ServerSub。
  • ServerSub对返回值进行编码并发送回消费端。
  • clientSub对返回进行解码。
  • 服务消费端得到调用结果。
RPC就是把2-7封装起来,然后消费端只需编码1的代码,和8的代码。
实战

这个demo仅仅使用了String类型的编解码器,也就是说只能进行String类型的数据传输。但也麻雀虽小,五脏俱全了。完成了基本的RPC通信。
代码量有点多,这里就直接上GitHub了,然后下面说说逻辑。
有三个包模块:

rpc-api:公共接口。
rpc-client:消费端。
rpc-provider:提供端。
使用方式:
服务端


  • 服务端配置文件配置服务提供者。
    目次固定是类路径下的providerconfig目次下的配置文件,不包罗子目次。


    服务端的配置文件只有2个项,分别是提供者的id,提供者的类全限定名称。
  1. public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, IOException, InterruptedException {        //参数1位端口,参数2为业务线程池的巨细。        RpcServer rpcServer = new RpcServer(5858,100);        //启动        rpcServer.start();    }
复制代码
结果:

启动消费者:


  • 配置消费者配置文件:固定下面貌录下的配置文件。


    启动:
  1. public class Testst {    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, IOException {        ClientBootStrap clientBootStrap = new ClientBootStrap();        clientBootStrap.initClient();        HelloService helloServiceConsumer = (HelloService) clientBootStrap.getConsumer("HelloServiceConsumer");        System.out.println(helloServiceConsumer.sayHallo("Yehaocong"));        HelloService helloService = (HelloService) clientBootStrap.getConsumer("HelloServiceConsumer1");        System.out.println(helloService.sayHallo("Yehaoxian"));    }}
复制代码
为了测试同一个客户端可以调用差别服务(ip/port不一样)提供者,我们启动两个服务端提供者,一个用5959端口,一个用5858端口。
然后测试:

远程调用乐成。
大抵原理

提供端:


  • 服务启动时,剖析配置文件,生成服务提供者,用一个map维护。这个代码在server.RpcServer#initProvider方法中。
  • 当有消费端调用时,提供方NettyIO线程吸收到数据后,转发给业务线程池调用。

  • 业务线程池剖析url,找到对应的提供者对象和对应的方法,执行调用,并返回结果给消费端。
    runable.ServiceRunnable#run方法。
消费端


  • ClientBootStrap启动时,剖析配置文件,生成消费者对象,用client维护,实际上生成的是用动态署理署理过的stub对象。bootstrap.ClientBootStrap#initClient方法。
  • 想要用某个消费者调用远程,就使用ClientBootStrap.getConsumer方法并传入消费者id,获取消费者调用。

  • 消费者调用实际上是执行stub.ClientStub#invoke方法。拼接url,进行url发送到服务端。阻塞等待结果返回,阻塞方式使用线程的wait和notify机制。
  • 执行使用业务线程来执行,使用NettyIO线程专注IO。
消费端和服务端采用一个自界说编码器和Netty自带的LengthFieldBasedFrameDecoder解码器来管理粘包拆包问题。
测试代码:

结果:

GitHub地点:
https://github.com/YeHaocong1/rpc-demo

来源:https://blog.csdn.net/qq_40837310/article/details/111872314
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

发布主题

专注素材教程免费分享
全国免费热线电话

18768367769

周一至周日9:00-23:00

反馈建议

27428564@qq.com 在线QQ咨询

扫描二维码关注我们

Powered by Discuz! X3.4© 2001-2013 Comsenz Inc.( 蜀ICP备2021001884号-1 )