摘要:大概解释了什么是rpc以及rpc的注意事项,还有各个rpc框架
RPC(Remote Procedure Call),远程过程调用。它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的思想,RPC是一种技术思想,而非具体的一种规范或协议。在先介绍远程过程调用之前,然后再介绍一下什么是本地调用,皮一下,嘿嘿。就是你想次饭,然后自己去厨房做了开火,炒菜焖饭,顶天就是开个多线程,同时做这些事情,做完了之后还得自己屁颠屁颠的端到饭桌上,开次。远程过程调用就是你打开饿了么,订了个外卖,厨师去厨房炒菜做饭,你不用去自己做这些事情,只需要等待外卖小哥(网络传输层)把好吃的饭菜(数据结果)送过来。这么说,是不是很容易理解。
个人理解,rpc的起源为分布式,是分布式促使了rpc的诞生。
在我看来,一个高性能的RPC应该尽量避免使用http协议,毕竟我只是想传输一下数据而已,何必动用到一个文本传输的应用层协议呢,应该使用一些效率更高的通信协议,比如说UDP或者是TCP,但是不管你用何种协议进行数据传输,一个简化版的RPC框架结构如同下图
从上图可以看出, RPC 本身是 client-server模型,也是一种 request-response 协议。
有些实现扩展了远程调用的模型,实现了双向的服务调用,但是不管怎样,调用过程还是由一个客户端发起,服务器端提供响应,基本模型没有变化。
服务的调用过程为:
为了不了解微服务的童鞋好理解,先抛出了一个简易的流程图。但是在项目当中来说一个完整的微服务不仅仅是只有上图那些东西,还有服务注册,服务发现、负载、容错、网络传输、序列化,反序列化等组件。其中“RPC 协议”就指明了程序如何进行网络传输和序列化。
1、服务端如何确定客户端要调用的函数;
在远程调用中,客户端和服务端分别维护一个【ID->函数】的对应表, ID在所有进程中都是唯一确定的。客户端在做远程过程调用时,附上这个ID,服务端通过查表,来确定客户端需要调用的函数,然后执行相应函数的代码。
2、如何进行序列化和反序列化;
客户端和服务端交互时将参数或结果转化为字节流在网络中传输,那么数据转化为字节流的或者将字节流转换成能读取的固定格式时就需要进行序列化和反序列化,序列化和反序列化的速度也会影响远程调用的效率。
只有二进制数据才能在网络中传输,序列化和反序列化的定义是:
3、如何进行网络传输(选择何种网络协议);
多数RPC框架选择TCP作为传输协议,也有部分选择HTTP。如gRPC使用HTTP2。不同的协议各有利弊。TCP更加高效,而HTTP在实际应用中更加的灵活。
4、服务注册中心;
服务注册中心用来实现服务发现和服务的元数据存储。常见的服务注册中心,点对点,点对多,zookeeper,etcd,Consul,mDNS等
目前流行的开源 RPC 框架还是比较多的,有阿里巴巴的 Dubbo、Facebook 的 Thrift、Google 的 gRPC、Twitter 的 Finagle ,以及国人开发的rpcx。
如下是一个Dubbo的设计架构图,分层清晰,功能复杂,嗯,极其复杂
哦吼,真是
1.RPC 核心之网络传输协议
在 RPC 中可选的网络传输方式有多种,可以是 TCP 协议、KCP协议、UDP 协议、QUIC协议,HTTP1以及HTTP2 协议。
每一种通信协议对业务的性能和效率都有不同的影响,如何选择一个正确的网络传输协议呢?首先要搞明白各种传输协议在 RPC 中的工作方式。
接下来我主要介绍TCP跟HTTP的调用流程以及区别
由微服务的客户端以及服务端建立 Socket 连接,并由客户端通过 Socket 将需要调用的接口名称,方法名称,序列化后的数据传递给服务端处理,然后服务端通过反序列化后的信息反射调用相关的方法。
最后将处理好的结果返回给客户端。整体流程基本上就是这样。
该方法更像是访问网页一样,只是它的返回结果更加单一简单。
大致流程为:由微服务的客户端向服务端发送请求,这种请求的方式可能是 GET、POST、PUT、DELETE 等中的任意一种,服务端会根据不同的请求方式做出不同的处理,或者某个方法只允许某种请求方式。
而调用的具体方法则是根据 URL 进行方法调用,而方法所需要的参数可能是对服务调用方传输过去的 XML 数据或者 JSON 数据解析后的结果,最后返回 JOSN 或者 XML 的数据结果。
两种方式对比
基于 TCP 的协议实现的 RPC 调用, TCP 协议处于协议栈的下层,能够更加灵活地对协议字段进行定制,减少网络开销,提高性能,实现更大的吞吐量和并发数。但是需要更多关注底层复杂的细节,实现的代价更高。同时对应不同应用平台,需要选择不同的工具包来进行请求发送和相应解析,工作量大。
基于 HTTP 协议实现的 RPC 则可以使用 JSON 和 XML等 格式的请求或响应数据。json以及xml等通用格式标准在各个编程语言下的解析工具已经非常成熟,不需要过多的关注。所以说在其基础上进行开发会非常简单。但是正是由于http的可靠以及简单。所以相对比TCP协议更加的效率低还有耗资源。因为http协议是上层协议。要包含更多的内容信息,来保证其可靠性。所以说在网络传输要占用的更多的字节数。
因此在同等网络下,通过 HTTP 协议传输相同内容,效率会比基于 TCP 协议的数据效率要低,信息传输所占用的时间也会更长,当然压缩数据,能够缩小这一差距。
使用 RabbitMQ 的 RPC 架构
在 OpenStack 中服务与服务之间使用 RESTful API 调用,而在服务内部则使用 RPC 调用各个功能模块。
正是由于使用了 RPC 来解耦服务内部功能模块,使得 OpenStack 的服务拥有扩展性强,耦合性低等优点。
OpenStack 的 RPC 架构中,加入了消息队列 RabbitMQ,这样做的目的是为了保证 RPC 在消息传递过程中的安全性和稳定性。
使用 RabbitMQ 的好处:
RabbitMQ 的三种类型的交换器
RabbitMQ 使用 Exchange(交换机)和 Queue(队列)来实现消息队列。
在 RabbitMQ 中一共有三种交换机类型,每一种交换机类型都有很鲜明的特征。
广播式交换器(Fanout)
该类型交换器不分析所接收到消息中的 Routing Key,默认将消息转发到所有与该交换器绑定的队列中去。
直接式交换器(Direct)
该类交换器需要精确匹配 Routing Key 与 Binding Key,如消息的 Routing Key = Cloud,那么该条消息只能被转发至 Binding Key = Cloud 的消息队列中去。
主题式交换器
该类交换器通过消息的 Routing Key 与 Binding Key 的模式匹配,将消息转发至所有符合绑定规则的队列中。
Binding Key 支持通配符,其中“*”匹配一个词组,“#”匹配多个词组(包括零个)
RabbitMQ连接设计
RabbitMQ 实现的 RPC 对网络的一般设计思路:消费者是长连接,发送者是短连接。但可以自由控制长连接和短连接。
一般消费者是长连接,随时准备接收处理消息;而且涉及到 RabbitMQ Queues、Exchange 的 auto-deleted 等没特殊需求没必要做短连接。发送者可以使用短连接,不会长期占住端口号,节省端口资源。
介绍:Protocol Buffers 是一种与语言、平台无关,可扩展的序列化结构化数据的方法,常用于通信协议,数据存储等等。相较于 JSON、XML,它更小、更快、更简单,因此也更受开发人员的青眯
都是网络交互的协议规范。通常用于多个微服务之间的通信协议。
比较 | REST | REST |
---|---|---|
通信协议 | HTTP | 一般使用TCP |
性能 | 低 | 高 |
灵活度 | 高 | 低 |
REST和RPC都可以应用于微服务架构中。
最后对REST与RPC做一个小小的总结,REST的调用以及调试都特别方便 ,RPC跟起对比就麻烦一些,但是RPC的效率以及对分布式的支持以及动态扩容能力是毋庸置疑的,所以建议在分布式的内部调用的时候使用RPC,对外部提供服务的时候使用REST。