动态代理与RPC

简介: 动态代理与RPC

前后对比


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



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


  • IM-server 自然就是服务端了,用于和客户端保持长连接。


  • IM-client 客户端,可以简单认为是类似于的 QQ 这样的客户端工具;当然功能肯定没那么丰富,只提供了一些简单消息发送、接收的功能。


  • Route 路由服务,主要用于客户端鉴权、消息的转发等;提供一些 http 接口,可以用于查看系统状态、在线人数等功能。


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



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


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


  1. 先通过 http 将消息发送到 Route 服务。


  1. 路由服务得知 ClientB 是连接在 ServerB 上;于是再通过 http 将消息发送给 ServerB


  1. 最终 ServerB 将消息通过与 ClientB 的长连接通道 push 下去,至此消息发送成功。


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



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


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


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


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


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


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


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



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


  • 完全屏蔽了底层细节,可以更好的实现业务及维护代码。


  • 即便是服务提供方修改了参数,在编译期间就能很快发现,而像之前那样调用是完全不知情的,所以也增加了风险。


绕不开的动态代理


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


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


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



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


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


完整源码如下:



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



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


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


总结


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


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


本文的所有源码:


github.com/crossoverJi…


相关文章
|
Kubernetes 关系型数据库 MySQL
k8s教程(基础篇)-入门及案例
k8s教程(基础篇)-入门及案例
4380 0
|
Kubernetes Linux iOS开发
使用kubectl连接远程Kubernetes(k8s)集群
在自己本机当中安装kubectl并远程连接Kubernetes(k8s)集群。覆盖了Windows、MacOS和Linux操作系统,步骤超详细,在后面还有关于MacOS和Linux命令自动补全
1603 1
使用kubectl连接远程Kubernetes(k8s)集群
|
NoSQL 安全 网络协议
|
Kubernetes 安全 API
国内首个云上容器ATT&CK攻防矩阵发布,阿里云助力企业容器化安全落地
本文对云上容器ATT&CK攻防矩阵做了详细阐述,希望能帮助开发和运维人员了解容器的安全风险和落地安全实践。
国内首个云上容器ATT&CK攻防矩阵发布,阿里云助力企业容器化安全落地
|
网络协议 Java 应用服务中间件
在spring boot中配置HTTP/2
在spring boot中配置HTTP/2
在spring boot中配置HTTP/2
|
6月前
|
XML 安全 Apache
利用EXCEL进行XXE攻击
本文介绍了通过构造恶意 Excel 文件利用 XXE(XML 外部实体)漏洞的原理与实践。首先说明了文件如 Word、Excel 等以 ZIP 格式存储,包含多个 XML 文件的特点。当服务器未正确配置 XML 解析器时,可能导致文件泄露、远程代码执行或拒绝服务攻击等风险。接着详细描述了搭建测试环境的过程,包括使用 Apache POI 依赖读取 Excel 文件,修改 xlsx 文件中的 Content_Types.xml 添加外部实体引用,以及通过 DNSLog 验证漏洞存在。最后展示了如何利用外部 DTD 文件读取目标系统上的敏感文件,并将数据写入指定位置,完成攻击验证。
396 5
利用EXCEL进行XXE攻击
|
7月前
|
自然语言处理 安全 测试技术
HCL AppScan Standard 10.8.0 (Windows) - Web 应用程序安全测试
HCL AppScan Standard 10.8.0 (Windows) - Web 应用程序安全测试
401 0
HCL AppScan Standard 10.8.0 (Windows) - Web 应用程序安全测试
|
数据采集 安全 Java
Web 漏洞扫描之 BurpSuite(一)| 学习笔记
快速学习 Web 漏洞扫描之 BurpSuite(一)
1970 0
Web 漏洞扫描之 BurpSuite(一)| 学习笔记
|
监控 Linux Shell
Linux系统之部署Linux命令大全搜索工具
【7月更文挑战第24天】Linux系统之部署Linux命令大全搜索工具
355 3
Linux系统之部署Linux命令大全搜索工具
|
图形学
【制作100个unity游戏之26】unity2d横版卷轴动作类游9(附带项目源码)
【制作100个unity游戏之26】unity2d横版卷轴动作类游9(附带项目源码)
284 0