RPC 类型

现在我们知道了有四个 RPC 操作,我们可以看到它们是如何组合在一起,形成 gRPC 提供的不同 RPC 类型的。我们将讨论 Unary(单向 RPC)、Server Streaming(服务器流式 RPC)、Client Streaming(客户端流式 RPC)和 Bidirectional(双向 RPC)这几种类型。我们将看到,每种类型都是前面提到的 RPC 操作的组合。

单向请求

单向 RPC 是执行一次请求并返回一次响应的 RPC 类型。我们在前面的章节中已经提到过这一点,但现在让我们更清晰地理解这一过程。

与往常一样,第一步是客户端发送初始的头部信息。这个头部包含与我们想要调用的 RPC 端点相关的信息。到目前为止,我们只需要知道,它主要包括 RPC 路由和流 ID。前者是为了让服务器知道它应该调用哪个用户代码函数来处理请求,后者是用来标识数据应该通过哪个流发送,因为我们可以同时进行多个流。

由于服务器现在已经知道客户端将发送请求,客户端就可以发送实际的消息了。这个消息包含实际的请求有效负载。在我们的例子中,我们将只发送经过 Protocol Buffers 编码的数据,但要注意,你可以使用 gRPC 发送任何类型的数据。

之后,由于我们处于单向 RPC 设置中,客户端完成了请求的发送。如我们所知,客户端此时应发送 Half Close。这个操作告诉服务器:我完成了,请发送响应给我。

此时,服务器会进行类似的工作。如下图所示,服务器会发送一个头部信息,发送经过 Protobuf 编码的响应消息,并结束 RPC 调用。然而,正如我们所知,服务器不会发送 Half Close;它会发送 Trailer。Trailer 是一些数据,表示调用是否成功,是否有可选的错误消息,以及我们可以通过用户代码添加的其他键值对。

image 2024 12 31 19 04 43 675
Figure 1. Figure 1.3 – Unary RPC flow

服务器流式

服务器流式 RPC 是一种执行一次请求并返回一个或多个响应的 RPC 类型。这种 RPC 类型适用于客户端期望从服务器接收更新的情况。例如,我们可以让客户端显示选定公司股票的实时价格。在服务器流式 RPC 中,客户端可以订阅,服务器可以随时间发送不同的价格。

在这种情况下,客户端的操作不会改变。它会发送头部信息、消息和 Half Close。然而,在服务器端,我们将交替发送 HTTP 数据消息和数据有效负载。

如下面的图所示,服务器将首先发送它的头部信息。这是当一个参与者想要让另一个参与者知道它将发送消息时的常规做法。之后,如前所述,服务器将交替发送 HTTP 数据消息和 Protobuf 有效负载。第一次数据消息将类似于以下内容(简化版):

HyperText Transfer Protocol 2
    Stream: DATA, Stream ID: 1, Length 30
        Length: 30
        Type: DATA (0)
        Flags: 0x00
            0000 .00. = Unused: 0x00
            .... 0... = Padded: False
            .... ...0 = End Stream: False

这表示将发送一条消息。它是一个轻量级的头部信息。之后,当我们到达最后一条需要发送的消息时,服务器会通过 trailer 结束 RPC 调用,到那时,客户端就会知道服务器已经完成了所有响应的发送。

image 2024 12 31 19 07 49 228
Figure 2. Figure 1.4 – Server streaming flow

客户端流式

客户端流式 RPC 类似于服务器流式 RPC,但这次是客户端可以发送一个或多个请求,而服务器返回一个响应。这在客户端需要向服务器发送实时信息的情况下非常有用。例如,这可能对微控制器非常有用,它们将来自某种传感器的数据发送给服务器,并更新传感器当前测量的状态。

客户端流式 RPC 类似于服务器流式 RPC。如下面的图所示,客户端将执行服务器在服务器流式 RPC 中所做的操作。这意味着客户端会交替发送 HTTP 数据消息,这些消息类似于我们之前提到的服务器流式 RPC 中的数据消息,并与 Protobuf 消息交替发送。最后,当客户端完成时,它将简单地发送一个 Half Close。

image 2024 12 31 19 10 15 101
Figure 3. Figure 1.5 – Client streaming flow

双向流式

到目前为止,你可能已经猜到,双向流式 RPC 是服务器流式 RPC 和客户端流式 RPC 的结合。客户端可以发送一个或多个请求,服务器返回一个或多个响应。当其中一个参与者需要对其数据进行反馈时,这种 RPC 类型特别有用。例如,如果你有一个打车应用,仅仅让服务器发送关于出租车的更新信息可能不够。用户可能还会朝着目的地走,希望在路上遇到出租车。因此,服务器也需要知道用户的位置。

双向流式 RPC 比客户端流式和服务器流式更不可预测。这是因为每个参与者发送消息的顺序没有固定,服务器可以根据请求发送一个响应,也可以根据多个请求发送响应。因此,在这一节中,我们假设我们正在处理一个每次请求都返回响应的服务器。

在这种情况下,如下图所示,客户端将发送一个头部信息和一条消息。然后,服务器将发送它的头部信息和消息。之后,我们将看到每个参与者发送的数据和消息。最后,我们将看到客户端发送 Half Close,服务器发送 Trailer。

image 2024 12 31 19 12 20 522
Figure 4. Figure 1.6 – Bidirectional streaming flow