RPC框架的目标就是让远程服务调用更加简单、透明,RPC框架负责屏蔽底层的传输方式(TCP或者UDP)、序列化方式(XML/JSON/二进制)和通信细节。服务调用者可以像调用本地接口一样调用远程的服务提供者,而不需要关心底层通信细节和调用过程。
RPC框架的调用原理图如下所示:
业界主流的RPC框架整体上分为三类:
随着微服务的发展,基于语言中立性原则构建微服务,逐渐成为一种主流模式,例如:
因此,基于多语言的RPC框架来构建微服务,是一种比较好的技术选择。
例如Netflix的API服务编排层和后端的微服务之间就采用gRPC进行通信。
本文档介绍gRPC和protocol buffers,gRPC可以使用protocol buffers作为其接口定义语言(Interface Definition Language,IDL)和其基础消息交换格式。
在gRPC中,客户端应用程序可以直接调用不同计算机上的应用程序中的方法,就像它是本地对象一样,可以更轻松地创建分布式应用程序和服务。与许多RPC系统一样,gRPC基于定义服务的思想,指定可以使用其参数和返回类型的远程调用方法。
gRPC的调用示例如下所示:
gRPC客户端和服务端可以在各种环境中相互运行和通信(从Google内部的服务器到桌面应用),并且可以使用任何gRPC支持的语言编写。因此,可以使用Go,Python或Ruby轻松创建gRPC客户端与使用Java编写的gRPC服务端通信。此外,最新的Google API将具有gRPC版本的接口,可以轻松地在编写的应用程序中构建Google提供的功能和服务。
默认情况下,gRPC使用protocol buffers,这是Google成熟的开源机制,用于序列化结构化数据(尽管它可以与其他数据格式,如JSON一起使用)。
使用protocol buffers的第一步是,定义要在.proto
文件中序列化的数据的结构(这是一个扩展名为.proto
的普通文本文件)。
protocol buffers中的数据被构造为消息,其中每个消息是包含一系列称为字段的键值的逻辑记录。这是一个简单的例子:
message Person {
string name = 1;
int32 id = 2;
bool has_ponycopter = 3;
}
一旦指定了数据结构,就可以使用protocol buffers编译器protoc
从原型定义生成首选语言的数据访问类:
name()
和set_name()
将整个结构序列化为原始字节的方法
例如,如果选择的语言是C++,则运行编译器,上面的例子将生成一个名为
Person
的类。然后,可以在应用程序中使用此类来填充,序列化和检索Person protocol buffers消息。
正如将在示例中更详细地看到的那样,可以在普通的proto文件中定义gRPC服务,并将RPC方法参数和返回类型指定为protocol buffers消息:
// 服务定义
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply) ;
}
// 请求消息
message HelloRequest {
string name = 1;
}
// 响应消息
message HelloReply {
string message = 1;
}
gRPC还可以使用带有特殊gRPC插件的protoc
来生成proto文件中的代码。如果,使用gRPC插件,将获得生成的gRPC客户端和服务端代码,以及用于填充,序列化和检索消息类型的常规protocol buffers代码。
可以在Protocol Buffers文档中找到有关protocol buffers的更多信息,并了解如何使用所选语言的快速入门来获取和安装带有gRPC插件的protoc
。
虽然在很早之前,protocol buffers已经可供开源用户使用,但在示例中使用了一种新的protocol buffers,称为proto3,它具有略微简化的语法,一些有用的新功能,并支持更多语言。
目前提供Java,C++,Python,Objective-C,C#,lite-runtime(Android Java),Ruby和JavaScript,都来自protocol buffers GitHub repo,以及来自golang/protobuf GitHub的Go语言生成器,还有更多语言在开发中。
可以在proto3语言指南和每种语言的参考文档中找到更多信息,参考文档还包括.proto
文件格式的正式规范。
通常,虽然可以使用proto2(当前的默认protocol buffers版本),但建议将proto3与gRPC一起使用,因为它允许使用全系列的gRPC支持的语言,以及避免与proto2客户端与proto3服务端通信时的兼容性问题,反之亦然。