上图描述了一个RPC的完整调用流程:
1:client向client stub发起方法调用请求。
2:client stub接收到请求后,将方法名,请求参数等信息进行编码序列化。
3:client stub通过配置的ip和端口使用socket通过网络向远程服务器server发起请求。
4:远程服务器server接收到请求,解码反序列化请求信息。
5:server将请求信息交给server stub,server stub找到对应的本地真实方法实现。
6:本地方法处理调用请求并将返回的数据交给server stub。
7:server stub 将数据编码序列化交给操作系统内核,使用socket将数据返回。
8:client端socket接收到远程服务器的返回信息。
9:client stub将信息进行解码反序列化。
10:client收到远程服务器返回的信息。
上图中有一个stub(存根)的概念。
stub负责接收本地方法调用,并将它们委托给各自的具体实现对象。
server端stub又被称为skeleton(骨架)。可以理解为代理类。而实际上基于Java的RPC框架stub基本上也都是使用动态代理。
我们所说的client端和server端在RPC中一般也都是相对的概念。
而所谓的RPC框架也就是封装了上述流程中2-9的过程,让开发者调用远程方法就像调用本地方法一样。
如何选择
如果公司项目使用Java并不牵扯到跨语言,且规模并没有大到难以治理,我推荐Dubbo。如果项目规模大,服务调用错综复杂,我推荐SpringCloud。
如果牵扯到跨语言,我推荐gRPC,这也是目前我司的选择。即使Thrift性能是gRPC的2倍,但没办法,它有个好爹,现在我们的开发环境考虑最多的还是生态,不得不向Google爸爸臣服。
一个RPC框架必须有两个基础的组成部分:数据的序列化和进程数据通信的交互方式。
对于序列化gRPC采用了自家公司开源的Protobuf。什么是Protobuf?先看一句网络上 大部分的解释:
Google Protocol Buffer(简称 Protobuf)是一种轻便高效的结构化数据存储格式,平台无关、语言无关、可扩展,可用于通讯协议和数据存储等领域。
上句有几个关键点:它是一种数据存储格式,跨语言,跨平台,用于通讯协议和数据存储。
这么看和我们熟悉的JSON类似,但其实着重点有些本质的区别:
JSON主要是用于数据的传输,因为它轻量级,可读性好,解析简单。
Protobuf主要是用于跨语言的IDL,它除了和JSON、XML一样能定义结构体之外,还可以使用自描述格式定于出接口的特性,
并可以使用针对不同语言的protocol编译器产生不同语言的stub类。所以天然的适用于跨语言的RPC框架中。
而关于进程间的通讯,无疑是Socket。Java方面gRPC同样使用了成熟的开源框架Netty。使用Netty Channel作为数据通道。传输协议使用了HTTP2。
通过以上的分析,我们可以将一个完整的gRPC流程总结为以下几步:
项目需求:
go调用java传递请求参数,并接收java返回的数据。(项目中本人采用http方式建立go&java连接)
为了体现gRPC跨语言的特性,我们使用两种语言:Go实现server端,Java作为client端来实现
Step1:登录Google的 github下载对应Protocol Buffers版本 (本人下载all)
// Step1:安装 Protocol Buffer 依赖
// 注:Protocol Buffer 依赖于 autoconf、automake、libtool、curl
brew install autoconf automake libtool curl
// Step2:进入 Protocol Buffer安装包 解压后的文件夹(我的解压文件放在桌面)
cd Desktop/protobuf-3.6.1
// Step3:运行 autogen.sh 脚本
./autogen.sh
// Step4:运行 configure.sh 脚本
./configure
// Step5:编译未编译的依赖包
make
// Step6:检查依赖包是否完整
make check
// Step7:开始安装Protocol Buffer
make install
// 在 终端 下输入
protoc - - version
执行protoc命令如果返回如下信息说明安装成功
未完待绪。。。。