一不小心实现了RPC

作者 : 开心源码 本文共1835个字,预计阅读时间需要5分钟 发布时间: 2022-05-14 共363人阅读

image

前言

image
随着最近关注 cim 项目的人越发增多,导致提的问题以及 Bug 也在添加,在修复问题的过程中难免代码洁癖又上来了。

看着一两年前写的东西总是怀疑这真的是出自自己手里嘛?有些地方实在忍不住了便开始了漫漫重构之路。

前后比照

在开始之前先简单详情一下 cim 这个项目,下面是它的架构图:

image

简单来说就是一个 IM 即时通讯系统,主要有以下部分组成:

  • IM-server 自然就是服务端了,用于和用户端保持长连接。
  • IM-client 用户端,可以简单认为是相似于的 QQ 这样的用户端工具;当然功能一定没那么丰富,只提供了少量简单消息发送、接收的功能。
  • Route 路由服务,主要用于用户端鉴权、消息的转发等;提供少量 http 接口,可以用于查看系统状态、在线人数等功能。

当然服务端、路由都可以水平扩展。


image

这是一个消息发送的流程图,假设现在部署了两个服务端 A、B 和一个路由服务;其中 ClientAClientB 分别和服务端 A、B 保持了长连接。

ClientAClientB 发送一个 hello world 时,整个的消息流转如图所示:

  1. 先通过 http 将消息发送到 Route 服务。
  2. 路由服务得知 ClientB 是连接在 ServerB 上;于是再通过 http 将消息发送给 ServerB
  3. 最终 ServerB 将消息通过与 ClientB 的长连接通道 push 下去,至此消息发送成功。

这里我截取了 ClientARoute 发起请求的代码:

image
可以看到这就是利用 okhttp 发起了一个 http 请求,这样尽管能实现功能,但其实并不优雅。

举个例子:假设我们需要对接支付宝的接口,这里发送一个 http 请求自然是没问题;但对于支付宝内部各部门直接互相调用接口时那就不应该再使用原始的 http 请求了。

应该是由服务提供方提供一个 api 包,服务消费者只要要依赖这个包即可以实现接口调用。

当然最终使用的是 http、还是自己设置私有协议都可以。

也相似于我们在使用 Dubbo 或者者是 SpringCloud 时,通常是直接依赖一个 api 包,便可以像调用一个本地方法一样调用远程服务了,并且完全屏蔽了底层细节,不论是使用的 http 还是 其余私有协议都没关系,对于调用者来说完全不关心。

这么一说是不是有内味了,这不就是 RPC 的官方解释嘛。

对应到这里也是同样的道理,ClientRouteServer 本质上都是一个系统,他们互相的接口调用也应当是走 RPC 才正当。

所以我重构之后的变成这样了:

image

是不是代码也简洁了许多,就和调用本地方法一样了,而且这样也有几个好处:

  • 完全屏蔽了底层细节,可以更好的实现业务及维护代码。
  • 即使是服务提供方修改了参数,在编译期间就能很快发现,而像之前那样调用是完全不知情的,所以也添加了风险。

绕不开的动态代理商

下面来聊聊具体是如何实现的。

其实在上文《动态代理商的实际应用》 中也有讲到,原理是相似的。

要想做到对调用者无感知,就得创立一个接口的代理商对象;在这个代理商对象中实现编码、调用、解码的过程。

image

对应到此处其实就是创立一个 routeApi 的代理商对象,关键就是这段代码:

RouteApi routeApi = new ProxyManager<>(RouteApi.class, routeUrl, okHttpClient).getInstance();

完整源码如下:

image

其中的 getInstance() 函数就是返回了需要被代理商的接口对象;而其中的 ProxyInvocation 则是一个实现了 InvocationHandler 接口的类,这套代码就是利用 JDK 实现动态代理商的三板斧。

image

查看 ProxyInvocation 的源码会发现当我们调用被代理商接口的任意一个方法时,都会执行这里的 invoke() 方法。

invoke() 方法自然就实现了上图中提到的:编码、远程调用、解码的过程;相信大家很容易看明白,因为不是本次讨论的重点就不过多详情了。

总结

其实了解这些就也就很容易看懂 Dubbo 这类 RPC 框架的核心源码了,总体的思路也是相似的,只不过使用的私有协议,所以在编解码时会有所不同。

所以大家要是想自己动手实现一个 RPC 框架,不妨参考这个思路试试,当用自己写的代码跑通一个 RPChelloworld 时的感觉是和自己整合了一个 DubboSpringCloud 这样的第三方框架的感觉是完全不同的。

本文的所有源码:

crossoverJie/cim

你的点赞与分享是对我最大的支持

说明
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » 一不小心实现了RPC

发表回复