RPC (Remote Procedure Call)即远程过程调用,是分布式系统常见的一种通讯方法,已经有 40 多年历史。当两个物理分离的子系统须要创建逻辑上的关联时,RPC 是牵线搭桥的常见技术手段之一。除 RPC 以外,常见的多系统数据交互方案还有分布式消息队列、HTTP 请求调用、数据库和分布式缓存等。nginx
其中 RPC 和 HTTP 调用是没有通过中间件的,它们是端到端系统的直接数据交互。HTTP 调用其实也能够当作是一种特殊的 RPC,只不过传统意义上的 RPC 是指长链接数据交互,而 HTTP 通常是指即用即走的短连接。git
RPC 在咱们熟知的各类中间件中都有它的身影。Nginx/Redis/MySQL/Dubbo/Hadoop/Spark/Tensorflow 等重量级开源产品都是在 RPC 技术的基础上构建出来的,咱们这里说的 RPC 指的是广义的 RPC,也就是分布式系统的通讯技术。RPC 在技术中的地位比如咱们身边的空气,它无处不在,可是又有不少人根本不知道它的存在。github
本地过程调用数据库
RPC就是要像调用本地的函数同样去调远程函数。在研究RPC前,咱们先看看本地调用是怎么调的。假设咱们要调用函数Multiply来计算lvalue * rvalue的结果:缓存
1 int Multiply(int l, int r) { 2 int y = l * r; 3 return y; 4 } 5 6 int lvalue = 10; 7 int rvalue = 20; 8 int l_times_r = Multiply(lvalue, rvalue);
那么在第8行时,咱们实际上执行了如下操做:服务器
以上5步就是执行本地调用的过程。(20190116注:以上步骤只是为了说明原理。事实上编译器常常会作优化,对于参数和返回值少的状况会直接将其存放在寄存器,而不须要压栈弹栈的过程,甚至都不须要调用call,而直接作inline操做。仅就原理来讲,这5步是没有问题的。)网络
远程过程调用带来的新问题框架
在远程调用时,咱们须要执行的函数体是在远程的机器上的,也就是说,Multiply是在另外一个进程中执行的。这就带来了几个新问题:socket
因此,要实现一个RPC框架,其实只须要把以上三点实现了就基本完成了。分布式
Call ID映射能够直接使用函数字符串,也可使用整数ID。映射表通常就是一个哈希表。
序列化反序列化能够本身写,也可使用Protobuf或者FlatBuffers之类的。
网络传输库能够本身写socket,或者用asio,ZeroMQ,Netty之类。
最后,有兴趣的能够看咱们本身写的一个小而精的RPC库 tinyrpc(hjk41/tinyrpc),对于理解RPC如何工做颇有好处。
---------------------------------------------------------------------------------------------------------------
SOA的发展
咱们在作一个访问量不大的项目的时候,一台服务器部署上一个应用+数据库也就够了.
那么访问量稍微大一点以后呢,为了解决用户反馈的卡,反应慢的状况,咱们就上集群.架设nginx,部署多个服务,由nginx负责把请求转发到其余服务上,这样就解决了用户说的卡慢问题.
过了一段时间以后呢,咱们发现数据库已经扛不住了,应用服务无缺,数据库有时候宕机. 那这个时候呢,咱们就上数据库读写分离,再架设几台数据库服务器,作主从,作分库分表. 而后数据库也不宕机了,服务又恢复了流畅.
又过了一段时间,公司事业增增日上,服务访问量愈来愈高,且大部分都是查询, 吸收以前宕机且为了办证数据库的健壮性,咱们这个时候又加上了缓存, 把用户高频次访问的数据放到缓存里.
后来,项目功能愈来愈多,整个项目也愈发庞大,修改一个类就须要全盘上传,切换nginx重启,这样的发布流程愈来愈长,愈来愈繁杂.而后咱们开始把模块拆分,用户信息分个项目,订单系统分一个项目.这样就达到了,用户模块代码修改的时候,只须要更新用户信息服务就行了.可是仍是须要切换顶层的nginx.把要重启的服务的流量切到可用服务上. 这个时候咱们就想到了RPC
那么RPC解决了什么呢? 全部的服务在启动的时候注册到一个注册机里面,而后顶层处理在接收到nginx的请求时,去注册机找一个可用的服务,并调用接口. 这样子呢,在不加新功能的时候,顶层处理服务咱们就不须要动了? 那修改了用户信息项目的时候,咱们只须要一个个更新用户信息项目的服务群就行了?
这样的话,不管是扩展仍是服务的健壮性都妥妥的了