共计 1407 个字符,预计需要花费 4 分钟才能阅读完成。
Angular8 正式发布了,Java13 再过几个月也要发布了,技术迭代这么快,框架的复杂度越来越大,但是原理是基本不变的。所以沉下心看清代码本质很重要,这次给大家带来的是手写 RPC 框架。
完整代码以及说明文档,点我跳跃~
1. 什么是 RPC?
RPC 是指远程过程调用,也就是说两台服务器 A,B,一个应用部署在 A 服务器上,想要调用 B 服务器上应用提供的函数 / 方法,由于不在一个内存空间,不能直接调用,需要通过网络来表达调用的语义和传达调用的数据。
RPC 框架有很多,比较知名的如阿里的 Dubbo、google 的 gRPC、Go 语言的 rpcx、Apache 的 thrift,新浪的 motan 等等。当然了,你也可以说 Dubbo 是 RPC 框架的超集,此外对于 Spring Cloud 来说,RPC 也只是它的一个功能模块。(话说 Dubbo 已经晋升为 Apache 顶级项目了,还不一起动手学习下?)
RPC 要解决的两个问题:
- 解决分布式系统中,服务之间的调用问题。
- 远程调用时,要能够像本地调用一样方便,让调用者感知不到远程调用的逻辑。
2. 技术选型
- SpringBoot
项目的基础框架,提供 IoC 功能。同时方便打成 JAR 包,便于测试。
- Netty
基于 NIO 的网络通信框架。相比用 java socket 实现的 BIO 通信,Netty 无论是代码编写简洁还是基于 NIO 异步非阻塞特性,都占尽了优势。
- fastjson
序列化、反序列化。RPC 框架中通信选择有很多:kyro/thift/json/hessian/protobuf/xml 等等,为了快速实现 RPC 框架,节省生成桩函数的时间成本,所以本文采用了阿里的 fastjson。
- zookeeper
提供服务的发现与注册。一个服务会有多个实例,所以我们选用 zookeeper 作为注册中心,在调用时,从 zookeeper 获取服务的实例列表,再从中选择进行调用。
3. RPC 实现流程
消费者端流程:
- 代理服务接口
- 服务发现(连接 zookeeper,获取生产者列表)
- 远程调用(轮询生产者服务列表),将类名,方法名和参数等信息通过代理发送给生产者端
生产者端流程:
- 加载需要远程调用的服务,并缓存
- 启动通讯服务器(Netty)
- 服务注册(把通信地址放入 zookeeper)
- 收到消息后使用反射,本地调用方法并将执行的结果编码返回给消费者端
在调用链路中断点,就可以同时了解 RPC 通信原理和 Netty 的通信原理了,代码每个方法和类都做了注释~ 实践出真知,看代码胜过所有博客的文字介绍。
4. 未实现的功能
相比 Dubbo 这样成熟的 RPC 框架还有未实现的功能如下:
- 负载均衡
如何从多个实例里挑选一个出来,进行调用,这就要用到负载均衡了。负载均衡的策略肯定不只一种,要怎样把策略做成可配置的?又要如何实现这些策略?
- 结果缓存
每次调用查询接口时都要真的去 Server 端查询吗?是不是要考虑一下支持缓存?
- 多版本控制
服务端接口修改了,旧的接口怎么办?
- 异步调用
客户端调用完接口之后,不想等待服务端返回,想去干点别的事,如何支持?
- 优雅停机
服务端要停机了,还没处理完的请求,如何优雅的处理?
最后,限于笔者经验水平有限,欢迎读者就文中的观点提出宝贵的建议和意见。如果想获得更多的学习资源或者想和更多的是技术爱好者一起交流,可以关注我的公众号『全菜工程师小辉』后台回复关键词领取学习资料、进入前后端技术交流群和程序员副业群。同时也可以加入程序员副业群 Q 群:735764906 一起交流。