gRPC + Protobuf专题介绍

Protobuf(Protocol Buffers)

简介

Protocol Buffers是一种与语言、平台无关的可扩展机制,用于序列化结构化数据。它类似于JSON,但是更轻量、速度更快,而且可以生成原生语言绑定。一旦定义了数据的结构化方式,就可以通过多种语言使用特殊的生成源代码来读写结构化数据。Protocol Buffers包括文件中创建的定义语言、proto编译器为数据交互生成的代码、特定语言的运行库以及写入文件(或通过网络连接发送)的数据序列化格式。

针对大小不超过几兆字节的类型化、结构化数据包,Protocol Buffers提供了一种序列化格式。这种格式既适合短期的网络流量,也适合长期的数据存储。Protocol Buffers还可以通过新信息进行扩展,从而避免使现有数据无效或更新代码。

示例

Protocol Buffers是Google最常用的数据格式。其广泛用于服务器间通信以及磁盘上数据的存档存储。Protocol Buffers的messages和services示例如下。

message Person {
  optional string name = 1;
  optional int32 id = 2;
  optional string email = 3;
}

在文件的构建时,调用proto编译器生成各种编程语言的代码,以操作相应的protocol buffer。每个生成类都包含用于每个字段的访问器以及用于序列化整个结构和解析为原始字节的方法。以下是调用生成方法的一个例子。

Person john = Person.newBuilder()
    .setId(1234)
    .setName("John Doe")
    .setEmail("jdoe@example.com")
    .build();
output = new FileOutputStream(args[0]);
john.writeTo(output);

优势

  • 数据存储紧凑
  • 解析迅速
  • 许多编程语言都可用
  • 自动生成类优化功能

工作方式

下图展示了Protocol Buffers的工作流程:protoc编译器通过.proto文件生成相应语言的代码,然后项目代码和PB(Protocol Buffers)代码一起编译,获得编译的类,最后使用PB的类就可以对数据进行序列化、反序列化等操作。

在这里插入图片描述

gRPC

简介

gRPC是一个开源高性能远程过程调用(Remote Procedure Call,RPC)框架,可以在任何环境中运行。它可以高效地连接数据中心内和跨数据中心的服务,支持负载平衡、跟踪、运行状况检查和身份验证。它也可以应用于分布式计算,将设备、移动应用程序和浏览器连接到后端服务。

在gRPC中,客户机应用程序可以像本地对象一样直接调用不同机器上的服务器应用程序上的方法,使分布式应用程序和服务的创建更便捷。与许多RPC系统一样,gRPC基于定义服务的思想,指定远程调用的方法及其参数和返回类型。在服务器端,服务器实现这个接口,并运行gRPC服务器来处理客户端调用。在客户端,客户端有一个提供相同方法的存根(在某些语言中称为客户端)。下图展示了gRPC的工作原理。

在这里插入图片描述

gRPC客户端和服务器可以在各种环境中运行并相互通信,并且可以用任何gRPC支持的语言编写。例如,可以用Java创建gRPC服务器,用Go、Python或Ruby创建客户端。此外,最新的Google api将提供gRPC版本的接口,将Google功能构建到应用程序中会更方便。

核心概念

服务定义

和许多RPC系统一样,gRPC基于定义服务的思想,指定可以远程调用的方法及其参数和返回类型。默认情况下,gRPC使用Protocol Buffers作为接口定义语言(IDL)来描述服务接口和负载消息的结构。以下示例定义了一个名为 HelloService 的 gRPC 服务,以及两个消息类型 HelloRequestHelloResponse

service HelloService {
  rpc SayHello (HelloRequest) returns (HelloResponse);
}

message HelloRequest {
  string greeting = 1;
}

message HelloResponse {
  string reply = 1;
}

gRPC有四种定义服务方法:

  1. 一对一RPCs:客户端向服务器发送单个请求并获得单个响应,就像普通的函数调用一样。

    rpc SayHello(HelloRequest) returns (HelloResponse);
    
  2. 服务器流RPCs:客户端向服务器发送请求并获得读取消息序列的流。客户端从返回的流中读取,直到没有消息。gRPC保证了单个RPC调用中的消息排序。

    rpc LotsOfReplies(HelloRequest) returns (stream HelloResponse);
    
  3. 客户端流RPCs:客户端写入消息序列并将它们发送到服务器,同样使用提供的流。一旦客户端完成了消息的写入,它将等待服务器读取消息并返回其响应。gRPC同样保证了单个RPC调用中的消息排序。

    rpc LotsOfGreetings(stream HelloRequest) returns (HelloResponse);
    
  4. 双向流RPCs:服务器和客户端都使用读写流发送消息序列,这两个流独立运行,因此客户端和服务器可以按照任意顺序进行读写。例如,服务器可以等待接收到所有客户端消息后再写入响应,或者它可以交替地读取消息然后写入消息,或者其他一些读写组合。另一方面,每个流中的消息顺序依然被固定。

    rpc BidiHello(stream HelloRequest) returns (stream HelloResponse);
    
API使用

从.proto文件中的服务定义开始,gRPC提供了protocol buffer编译器插件,用于生成客户端和服务器端代码。gRPC用户可以在客户端调用这些API,并在服务器端实现相应的API。

服务器端实现服务声明的方法,并运行gRPC服务器来处理客户端调用。gRPC基础架构解码传入请求,执行服务方法,并编码服务响应。

客户端有一个本地对象,称为存根(某些语言称为客户机),它实现与服务相同的方法。然后,客户端可以在本地对象上调用这些方法。这些方法将调用的参数封装在适当的protocol buffer消息类型中,将请求发送到服务器,并返回服务器的protocol buffer响应。

同步和异步

同步RPC调用在收到服务器响应之前会一直阻塞,这是RPC力求达到的对过程调用的抽象近似。但是另一方面,网络本质上是异步的,在许多情况下,能够在不阻塞当前线程的情况下启动RPCs是有益的。大多数语言中的gRPC编程API都有同步和异步两种风格。

RPC生命周期
一对一RPC

客户端调用了存根方法后,服务器会收到RPC调用的通知,其中包含该调用的客户端元数据、方法名称和指定的截止日期(如果可用)。然后服务器可以直接发送回自己的初始元数据(必须在响应之前发送),或者等待客户端的请求消息。首先发生的是特定于应用程序的。

服务器获得了客户机的请求消息后,会执行创建和填充响应所需的所有工作,然后将响应(如果成功)连同状态详细信息(状态代码和可选状态消息)以及可选的尾随元数据一起返回给客户机。如果响应状态为OK,则客户机将获得响应,从而完成客户机端的调用。

服务器流RPC

服务器流RPC类似于一对一RPC,不同之处在于服务器在响应客户端的请求时返回消息流。发送完所有消息后,服务器的状态详细信息(状态码和可选状态消息)和可选的尾随元数据被发送到客户端,到此服务器端工作结束。客户机在获取所有服务器消息后完成工作。

客户端流RPC

客户端流RPC类似于一对一RPC,不同之处是客户端向服务器发送消息流而不是单个消息。通常在接收到所有客户机的消息之后,服务器用一条消息(连同它的状态详细信息和可选的尾随元数据)进行响应,

双向流RPC

在双向流RPC中,调用由客户端和服务器共同发起,其中客户端调用方法,服务端接收客户端元数据、方法名称和截止日期的。服务器可以选择发回其初始元数据,或者等待客户端开始流式传输消息。

客户端和服务器端流处理是特定于应用程序的。由于这两个流是独立的,客户端和服务器可以以任何顺序读写消息。例如,服务器可以等到接收到客户端的所有消息后再写入消息,或者服务器和客户端可以“打乒乒球”——服务器收到请求,然后发回响应,然后客户端根据响应发送另一个请求,以此类推。

截止时间和超时

gRPC允许客户端指定等待RPC完成的时间,超时后DEADLINE_EXCEEDED错误终止。在服务器端,服务器可以查询特定RPC是否超时,或者还剩多少时间来完成RPC。

指定截止日期或超时是依语言而定的:一些语言api根据超时(时间段)工作,而另一些语言api根据截止时间(具体时刻)工作,同时可能有也可能没有默认的截止时间。

RPC终止

在gRPC中,客户机和服务器都独立在本地对调用是否成功作出判断,但二者的结论可能不匹配。这意味着可能有一个RPC在服务器端成功完成(发送了所有响应),但在客户端接受失败(响应在截止时间之后到达)。服务器也有可能在客户端发送所有请求之前决定完成。

撤销RPC

客户端或服务器都可以在任何时候撤销RPC。撤销将立即终止RPC,导致无法继续工作。注意,撤销之前所做的更改不会回滚。

元数据

元数据是的关于特定RPC调用的信息(例如身份验证细节),形式为键-值对列表,其中键是字符串,值通常是字符串,但也可以是二进制数据。

键不区分大小写,由ASCII字母、数字和特殊字符-_.组成。并且不能以grpc-(为grpc自身保留)开头。二进制值的键以-bin结尾,而ascii值的键不以-bin结尾。

gRPC不使用用户定义的元数据,它允许客户端向服务器提供与调用相关的信息,反之亦然

通道

gRPC通道用于连接指定主机和端口上的gRPC服务器,在创建客户端存根时使用。客户端可以指定通道参数来修改gRPC的默认行为,例如打开或关闭消息压缩。通道有状态,包括已连接和空闲。gRPC如何处理关闭通道取决于语言。有些语言还允许查询通道状态。

结语

值此网络程序设计结课之际,我想向孟宁老师表达我最诚挚的感谢。在您的网络程序设计课堂上,我获益匪浅,深感受益良多。感谢您的耐心教导和专业知识的分享。您深入浅出的讲解方式使得原本复杂的网络程序设计理念变得清晰易懂。您的教导不仅仅是专业知识的传授,更是对我们综合素养的培养,让我在课程中获得了更全面的提升。再次感谢您为我们呈现的精彩课程和对我们的悉心指导。您是一位出色的老师,让我在网络程序设计领域迈出了坚实的一步。

  • 29
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值