用 Netty 造一个简单的 RPC

本贴最后更新于 1801 天前,其中的信息可能已经时过境迁

一、项目结构

hotrpc-common

  • 主要代码
    • 自定义注解,用于标志代理类
    • netty 的相关操作,用于服务之间的通信
      • netty clientnetty server
      • 编码器,解码器
    • 服务接口的定义以及对服务实现类的扫描注册
      • 将服务实现类进行实例化
      • 当客户端调用服务时,找到相应的实现类,用实现类进行代理

该子项目主要用于客户端和服务端之间的通信,自定义了一个请求协议,请求格式如下:

header dataLength data
614756773 variable variable
  • 一次完整的请求一共有 3 个部分
    • header 占 4 字节为固定值 614756773,作为一个 魔数 使用,以此来校验请求是否合法
    • dateLength 占 4 字节,为一个变量,用来表示 data 有多少字节
    • data,传输的数据

hotrpc-server

  • 主要代码
    • 定义服务实现类

hotrpc-client

  • 主要代码
    • 扫描标有 RpcCaller 注解的接口,并代理,然后注册成 bean 放入 spring 容器中
    • 定义 controller,并且从 spring 容器中获取到 代理服务

二、主流程

客户端

  1. 启动 SpringBootApplication
  2. 扫描标有 RPC 注解的类
  3. 注册到 spring 容器中
    • 注册时使用 jdk 动态代理该类 代理类东西有点多看下面
  4. 从 spring 容器中获得该类,调用方法
  • jdk 动态代理过程
    • 先将服务接口封装成一个 Request 对象,包括设置 classNamemethodNameparams
    • 实例化一个 Client 对象,然后通过该对象将请求发送出去
    • 阻塞等待响应
    • 从响应结果中获取数据并返回

服务端

  1. 实例化 Server 并且启动
  2. 检查 Server 状态,保证不会重复启动
  3. 把 rpc 服务实现类扫描出来然后实例化,缓存在 Map 对象中
  4. 若有请求来临
    • 对请求进行解码
    • 获取到请求体,从而找到对应的 rpc 服务实现类
    • 调用服务实现类
    • 对调用结果进行编码
    • 发送结果给客户端

三、优化点

  • 目前如果需要定义一个 rpc 服务,必须在 hotrpc-common 里先定义接口,然后再 hotrpc-server 中定义实现类。
    可以改成 cglib 动态代理,这样就不必再定义接口了,也能让 hotrpc-common 封装的更好
  • hotrpc-client 中需要定义如何去扫描 RpcCaller,如何进行代理。
    这样做很不好,应该放在 hotrpc-common 包中去做这些事情。
  • 由于进行扫描类操作,是使用的 spring 的工具类 ClassPathScanningCandidateComponentProvider 所以都写死了包路径为 cn.hotpot
    可以使用 org.reflections 工具类来进行扫描。

源码

github

  • Netty

    Netty 是一个基于 NIO 的客户端-服务器编程框架,使用 Netty 可以让你快速、简单地开发出一个可维护、高性能的网络应用,例如实现了某种协议的客户、服务端应用。

    49 引用 • 33 回帖 • 22 关注

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...