【学习笔记】gRPC概述

本文详细介绍了gRPC体系结构,包括服务定义、ProtocolBuffers的应用、四种RPC类型(同步/异步)、生命周期管理、元数据和通道。重点讲解了服务的声明、API使用和不同RPC类型的交互过程。
摘要由CSDN通过智能技术生成

全文参考自:gRPC 官方Docs

1. 概述

1.1 gRPC体系

    在gRPC体系中,client可以像调用本地方法一样直接调用位于不同主机上的server方法,使得创建分布式应用和服务更加简便。就像许多RPC系统一样,gRPC基于服务定义的思想,定义了可以被远程调用的方法、参数及其返回类型。
    在server端,server运行gRPC server来处理client请求;在service端,client运行gRPC stub来提供server的相同方法。
    gRPC的体系结构示意图如下所示:
gRPC的体系结构示意图
    gRPC client和server可以在不同环境中独立运行、互相通信,并且可以以任何一个gRPC所支持的语言(如Go、Python、Ruby等)实现。除此之外,最新的Google APIs也会有对应的gRPC版本,可以轻松在应用中使用Google功能。

1.2 Protocol Buffers

    gRPC默认使用Protocol Buffers(proto3)进行数据传输。

    使用Protocol Buffers的第一步是定义数据的结构,使其能够序列化为.proto文件。结构化后的数据被称为消息(message),每一个message是一个小型逻辑信息记录,包含了一系列的<name, value>对,称为域(fields)。该结构举例如下:

message Person {
  string name = 1;
  int32 id = 2;
  bool has_ponycopter = 3;
}

    当结构定义完成后,可以使用protocol buffer编译器protoc去生成proto中指定语言的数据获取类(data access class),该类为每个field提供了基础方法,如name()set_name(),还有将整个结构与字节流互相转化的方法。例如,如果选择的目标语言是C++,那么运行编译器后将会生成一个名叫Person的类,可以在应用程序中使用、序列化、检索此类的Protocol Buffer messages。
    使用gRPC定义服务的举例如下:

// Greeter服务定义
service Greeter {
  // 使用RPC发送greeting
  rpc SayHello (HelloRequest) returns (HelloReply) {}
}

// 请求message定义
message HelloRequest {
  string name = 1;
}

// 相应message定义
message HelloReply {
  string message = 1;
}

    gRPC根据用户所编写的.proto文件,使用gRPC插件和protoc编译器生成gRPC client和service代码,protocol buffer代码可以被使用、序列化、检索message类型。

2. 核心概念

2.1 Service

    gRPC基于service进行构建,该service中声明了可以被远程调用的方法、参数、返回类型。
    gRPC默认使用protocol buffers作为接口定义语言(Interface Definition Language, IDL),用来描述service接口和负载message的结构。也可以使用其他结构代替protocol buffers。
    gRPC service可定义的类型有4种:

  • Unary RPCs (一元RPCs,1:1)
    • 1 request <=> 1 response
    • client发送一个请求,server返回一个响应(类似于标准函数调用)
rpc SayHello(HelloRequest) returns (HelloResponse);
  • Server streaming RPCs (Server流式RPCs,1:n)
    • 1 request <=> N response
    • client发送一个请求,server返回一序列响应(序列内能够保证读写操作顺序)
rpc LotsOfReplies(HelloRequest) returns (stream HelloResponse);
  • Client streaming RPCs (Server流式RPCs,n:1)
    • N request <=> 1 response
    • client发送一序列请求,server待接收到所有request后返回一个响应(序列内能够保证读写操作顺序)
    • client会保持等待
rpc LotsOfGreetings(stream HelloRequest) returns (HelloResponse);
  • Bidirectional streaming RPCs (双向流式RPCs,n:n)
    • N request <=> N response
    • client发送一序列请求,server返回一序列响应(序列内能够保证读写操作顺序)
    • 两个stream独立运行,可以按任意形式进行读写(server接收部分后返回or接收全部再返回)
rpc BidiHello(stream HelloRequest) returns (stream HelloResponse);

2.2 API的使用

    如前所述,通过使用.proto文件可以定义service,同时gRPC提供了protocol buffer编译器插件来生成client端和server端的代码。用户需要调用client端的APIs,并实现server端对应的API方法。

  • 在server端,server实现service中声明的方法,并运行gRPC server来处理client的调用请求。
  • 在client端,使用stub本地对象来实现service中同样的方法,这样client就可以仅调用本地对象的这些方法,并以protocol buffer message形式对调用request及其参数进行包装。gRPC将request发送至server,并返回server端的protocol buffer response。

2.3 同步(Synchronous) vs 异步(asynchronous)

    同步RPC会在得到response前保持阻塞,这是对RPC所希望的过程调用的最接近近似。但另一方面,网络本质上是异步的,在许多场景下都需要RPCs在不阻塞当前线程的情况下启动。
    大多数语言中的 gRPC API 都有同步和异步两种形式,可在具体语言中进行使用。

3. RPC生命周期

3.1 Service

3.1.1 Unary RPC

  1. 一旦client调用了自身的一个stub方法,server就会收到通知RPC已被调用,通知中包含该调用的client metadata、方法名称和指定的截止时间(如果适用)。
  2. 然后,server可以立即发回自己的初始metadata(必须在任何response之前发送),或者等待client的request message。哪个先发生视具体情况而定。
  3. 一旦server收到了client的request message,它会执行创建和生成response所需的任何工作。然后将response连同其状态详细信息(状态码和可选状态 message)和可选附属metadata一起返回(如果成功)给client。
  4. 如果response的返回状态为OK,则client在收到这一response后就会结束这次调用

3.1.2 Server streaming RPC

    Server streaming RPC与Unary RPC类似,除了server会针对client的一个request返回一序列的message。
    当server所有的message都被发送出去后,server的状态详细信息(状态码和可选状态message)和可选附属metadata会被发送给client。
    server端将会在所有message发送完成后结束;client端将在收到所有server message后结束。

3.1.3 Client streaming RPC

    Client streaming RPC与Unary RPC类似,除了client会发送一序列的message给server,而不是单个message。
    server response的内容是单个message,内容包括:状态详细信息和可选附属metadata会被发送给client,这一response message的发送并不一定要在所有client信息都被接收到后才发送。

3.1.4 Bidirectional streaming RPC

    在Bidirectional streaming RPC中,调用由调用方法的client发起,server接收client metadata、方法名称和截止时间。server可以选择发回其初始metadata或等待client开始流式传输message。
    client和server的流处理是特定于应用程序的。由于这两个流是独立的,因此client和server可以以任意顺序读写消息。例如,server可以等到它收到client的所有message后再写入它自己的message;或是client和server可以“打乒乓”——server收到request,然后发回response,然后client根据response发送另一个request……依此类推。

3.2 截止时间(Deadlines)/超时(Timeouts)

    gRPC允许client指定他们愿意等待RPC完成的时间,避免RPC因出现DEADLINE_EXCEEDED错误而终止。在server端,server可以查询某个RPC是否已经超时,或是还要多久RPC才可以完成。
    声明一个deadline或timeout的方法是语言相关的:一些语言使用timeout概念(表示持续时间);一些语言使用deadline概念(表示一个固定时间点),可能存在默认值。

3.3 RPC的终止(termination)

    在gRPC中,client和server都能够独立决定某次调用是否成功,这意味着他们可能产生不同的结论。例如:server认为自己已经发送了全部的response,而client却认为已经超时。还有可能server在client发送全部request前就提前结束了。

3.4 取消(Cancel)一个RPC

    client和server都能够在任意时间取消一个RPC。一次取消意味着RPC被立即终止,不会再执行任何的任务。

注意:在取消前所执行的改变不会被回滚。

3.5 元数据(metadata)

    metadata是一个键值对列表,包含了某一次RPC调用的信息(如权限验证等)。key为string,value可以为string或二进制数据。metadata对于gRPC自身而言是不可见的,它使得client能够提供与调用相关的信息给server,反之亦然。
    不同语言对metadata的获取方式是不同的。

3.6 通道(Channels)

    gRPC通道使得gRPC server能够连接到指定的主机地址和端口。当创建client stub时会使用到stub,client可以设定通道参数来修改gRPC的默认行为(如是否开启message压缩)。
    通道具有状态性(连接or空闲)。不同语言关闭gRPC通道的方式是不同的,一些语言也会支持通道状态的查询。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MomentNi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值