这里抛出几个问题:
- RPC是什么?
- 本地函数调用的流程是什么?
- RPC与HTTP,TCP有什么关系?
- 一个标准的RPC包含哪些流程?
- 什么是协议?
2.1、简介
RPC框架全称Remote Procedure Call,翻译过来就是远程调用,RPC出现的原因主要是为了解决分布式系统中不同系统之间的接口调用。RPC使子系统接口的实现和调用可以分布在不同的机器上,RPC的调用非常方便,就像本地调用接口实现一样,RPC调用对于调用者来说,基本上属于黑盒。
2.2、本地调用
在本地调用中,比如有一个main.go文件,编译器会通过一系列的操作,比如语法分析等生成目标bin文件,输入,输出编解码的一系列问题,编译器都帮你搞定了。但是在远程调用中这些却是我们自己需要考虑的。
例如以下代码:
1 | func main() { |
我们一眼就能看出这段demo的意思,但是计算机是肯定不可能直接认识的,通过编译器,编译后的bin文件,计算机就可以执行了。
通过上面的描述,引出第一个概念,就是协议,协议解决了最基本的沟通问题,当调用方与远程接口约定好了协议,就可以实现沟通,就像我们在本地实现一个main.go文件,然后编译器根据约定好的协议(语法,语义)生成bin文件供计算机执行。
2.3、协议
协议是一种程序员通过学习就可以理解的,相信在工作中交流用的最多的就是以下场景。
1 | hi,有没有读取视频列表的接口,把协议发我看看。 |
一般看到协议,就知道如何调用对方接口了,所以协议更像是人类的语言。
协议的三要素:
- 语法:例如go语言与java语言的写法就不一样,有各自的语言规则。
- 语义:一段带有意义的文本,例如:”10-1”就是有意义的,”10-你好”就是无意义的。
- 顺序:先执行1,在执行2,有严格的执行顺序。
所以,通过约定好的rpc协议,就可以实现各个系统服务之间的调用。
2.4、桩代码Stub
桩(Stub / Method Stub)是指用来替换一部分功能的程序段。桩程序可以用来模拟已有程序的行为(比如一个远端机器的过程)或是对将要开发的代码的一种临时替代。因此,打桩技术在程序移植、分布式计算、通用软件开发和测试中用处很大。
例如 googole的protocol buffers协议:
1 | syntax = "proto3"; |
定义好协议,通过protocol buffer 编译器 protoc
来生成创建grpc应用所需的特定客户端和服务端的代码。protoc如何安装可以直接google。
命令如下:
1 | protoc --go_out=plugins=grpc:. demo.proto |
通过proto生成的桩代码如下,具体的原理后面分析:
1 | // Code generated by protoc-gen-go. DO NOT EDIT. |
可以看到我们之前协议里定义的SayHello接口转换成以下的样子。
1 | // GreeterServer is the server API for Greeter service. |
通过proto生成了gRPC框架可以处理的桩代码。
2.5、RPC执行流程
- 执行client调用,触发请求
- client调用本地stub,对请求参数进行封装。
- 将封装好的请求包交给client的rpc框架,rpc框架进行打包发送。
- client发送请求到server(网络调用)。
- server端的rpc框架接收到消息包。
- server将消息报交给server stub对参数进行解包。
- 获取解包参数,进行逻辑处理生成结果。
- 最后反向执行以上流程,发送reponse给client。
2.6、RPC、TPC、HTTP
RPC最开始介绍过,就是Remote Procedure Call(远程调用),他代表一种调用方式,RPC可以通过HTTP协议实现,也可以通过Socket实现。既然Socket与HTTP都可以实现,为什么不直接用Socket或者HTTP呢?制定私有协议,在封装一下Socket或HTTP真的就香了吗?
首先谈Socket,写过的朋友都知道,想把它弄得很透彻,需要把那几本厚厚的Socket编程好好看看,为了解决门槛高的问题,公司会组建一个通信组,实现一个通用的Socket组件库,业务同学直接调用。调用方和服务提供方拉个会,把入参格式,出参格式,ip,端口都统一定义好,开始通信,如果有一方将之前约得好的规则改变,那整个通信就有可能不通了。
再谈HTTP,虽然HTTP实现调用都很简单,但是当我们的系统拥有上百个接口的时候,RPC的协议管理就体现出优势了。而且RPC的调用非常方便简洁,大部分的RPC框架也都是长连接,有效减少3次握手带来的网络开销。
2.7、总结
整篇基本上围绕之前提出的问题来描述,都是基础常识,也是奔着扫盲的初衷。就是因为这种RPC实现了简单的接口级别调用,现在大量的微服务架构得以推广,实践。