什么是RPC?
现在大大小小的微服务,服务之间的数据交换,大都使用 GRPC 来实现,所以从这个角度去看 GRPC 是一个非常有必要学习的知识点。
于是我决定更一个系列的 GRPC 文章,希望能帮助你了解 GRPC。
要学习 GRPC 必须先了解什么是 RPC,因为 GRPC 是 RPC 的一个延伸。
RPC(Remote Procedure Call)远程过程调用,简单的理解是一个节点请求另一个节点提供的服务。
说到远程过程调用,就得提一下本地过程调用,他们两个的区别是什么?
举个例子:
我现在需要添加我的商品库存数量,在程序里面往往会建一个对象来存储这个数量,比如叫 Goods。
本地过程调用:
通常我们会创建一个方法 GoodsAdd() 需要将商品对象 Goods 传入。
然后方法里面修改完毕后返回操作结果回去,因为是本地调用,所以通常是使用指针传递 Goods 对象。
远程过程调用:
和本地过程最大的区别是,这个 Goods 对象不在本地,通常是在别的服务器。
此时我们需要做的就是告诉这个服务他对应的 ID(Goods对象) 是多少,然后做什么操作(GoodsAdd方法及参数),处理完后传回处理结果。
说得再直白点就是远程的去调用方法,并传过去参数。
RPC的由来
如果是在 N 多年前,流量不大的情况下,大都是单体服务,基本也都能抗住生产使用了,那时基本都是本地过程调用。
但是随着现在的流量越来越大,很明显单体服务是满足不了生产使用的,就开始有了模块分离,微服务产生。
开始把一些业务逻辑放到不同的服务器上来跑,于是服务与服务之间的调用场景,就产生了 RPC。
RPC 与 REST API 的区别
提到服务与服务之间的调用,大家最常见的就是 REST API 。
服务方提供一个接口文档,调用方按照这个接口文档调用接口,这貌似挺合理的。
但是也有不好的地方:
REST API 更擅长对资源进行 CRUD 操作。
通常 REST API 对一个资源进行增删改查是非常直观的,但是如果要对特定的目的操作就比较不那么直观了。
比如:要给名为张三的学生数学成绩加上10分。
虽然 REST API 也能通过更新操作进行操作,但是毕竟不是那么直观。
而 RPC 他是直接把方法抛出去了,直接调用方法为 Student.Increment(Name,Sore) 的方法就完成了,看着是不是更加直观。
RPC 更高效。
RPC 可以通过 TCP 进行长连接,在调用量非常大的时候是非常有优势的。
当然 RESTful 也可以通过 keep-alive 实现长连接,但是它最大的一个问题是它的request-response模型是阻塞的 ( http1.0 和 http1.1,http 2.0 没这个问题)。
说得直白点,发送一个请求后只有等到 response 返回才能发送第二个请求,RPC 的实现没有这个限制。
所以在如今大流量的情况下,RPC 更出色。
怎么定义入参和出参
RPC 是直接把方法给抛出去的,所以客户端和服务器端是紧耦合的。
客户端需要知道调用的这个方法名字,相关的参数以及它们的类型、顺序等。
一旦服务器更改了过程的实现,客户端的实现很容易出问题。
这里面该怎么去定义这个入参和出参呢?
如果不规范起来,百花齐放的,到时各个系统对接就非常难。
于是我们的老大哥——谷歌 就站出来了。
他说:我定义了一个 GRPC 协议,我不赚钱,我是第三方,一定会公立、公正的定义好协议,于是就出了一个 GRPC 协议。
于是大家就听大哥哥的用 GRPC 了,很多第三方库也兼容支持了 GRPC。
那他是怎么做到公正、公立的呢?
思路很简单:
我搞一个编译器,并定义一个规范,你只管按照规范定义传参和出参就行,剩下的我编译器帮你处理。
所以你就会发现在接入了 GRPC 的项目里面都能看到 .proto 文件的身影,他就是去定义每个请求相关的参数是什么,收到的是什么。
剩下的就不用你管了,是不是感觉有老大带头真爽。
所以一个完整的 GRPC 系统,都需要哪些支持呢?
1、client 和 service 肯定是需要有谷歌的解析依赖库,这个你可以不用关注,只管导入就好了。
2、定义出参、入参的规范 proto 文件。
下一篇我们接着讲,怎么去安装这些依赖。