Skip to content

gRPC

1. gRPC

[Figure 1] gRPC Architecture

[Figure 1] gRPC Architecture

gRPC is an RPC (Remote Procedure Call) Framework that can run in various environments. [Figure 1] shows the gRPC Architecture. The gRPC Server runs on the Service that processes requests, and the gRPC Stub runs on the Client. The Interface between the gRPC Server and the gRPC Stub is defined using ProtoBuf. The gRPC Server and the gRPC Stub communicate using HTTP/2. gRPC currently supports various languages such as Java, C++, Golang, Ruby, and Python.

1.1. ProtoBuf

ProtoBuf defines the Interface and performs Serialization of structured Data so that the Server and Client can easily exchange structured Data. It can be understood as a replacement for JSON, which is used as the Data format in REST APIs. However, unlike JSON, ProtoBuf converts Data into Binary form rather than Text form.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
message Person {
  string name = 1;
  int32 id = 2;
  string email = 3;

  enum PhoneType {
    MOBILE = 0;
    HOME = 1;
    WORK = 2;
  }

  message PhoneNumber {
    string number = 1;
    PhoneType type = 2;
  }
}
[File 1] addressbook.proto

[File 1] shows a .proto file that stores structured Person Data according to the ProtoBuf specification. ProtoBuf compiles the .proto file to generate Code that can be used by the gRPC Server and the gRPC Client. The Server and Client perform gRPC using the generated Code.

1.2. HTTP/2

gRPC operates by leveraging the advantages of HTTP/2 over HTTP/1.1.

  • Multiplexing, Stream : In HTTP/1.1, only one request could be processed at a time on a single TCP Connection, but HTTP/2 supports Multiplexing, which allows multiple requests to be processed simultaneously on a single TCP Connection. Multiple Streams are created on a single TCP Connection, and the Client and Server process each request independently using the created Streams. gRPC uses HTTP/2 Streams to process multiple RPCs simultaneously on a single TCP Connection.
  • Header Compression : HTTP/1.1 had no feature to compress Headers transmitted in plaintext, but HTTP/2 provides Header Compression to reduce Header size. gRPC Headers also use HTTP/2’s Header Compression feature to reduce their size.

1.2.1. RPC and Stream

1 TCP Connection
├── Stream 1 (RPC A) : HEADERS Frame → DATA Frame... → HEADERS Frame (Trailer)
├── Stream 3 (RPC B) : HEADERS Frame → DATA Frame... → HEADERS Frame (Trailer)
└── Stream 5 (RPC C) : HEADERS Frame → DATA Frame... → HEADERS Frame (Trailer)
[Text 1] Processing Multiple RPCs on a Single TCP Connection

A single RPC is mapped 1:1 to a single HTTP/2 Stream. As shown in [Text 1], every time the Client calls an RPC, a new Stream is dynamically created on the TCP Connection, and when the RPC completes, the Stream is also terminated. A single Stream is never shared or reused by multiple RPCs, and only Connection-level state (HPACK Header compression state, SETTINGS, Connection Flow Control Window) is shared by multiple Streams. The relationship between RPC and Stream has the following characteristics.

  • Stream creation is completed simply by the Client sending a HEADERS Frame with a new Stream ID, without any separate negotiation process. Therefore, even if a Stream is dynamically created for each RPC, no additional round-trip (RTT) cost such as TCP Connection establishment occurs.
  • Streams created by the Client are assigned odd Stream IDs (1, 3, 5…) in monotonically increasing order, and Streams created by the Server (Server Push) are assigned even Stream IDs (2, 4, 6…) in monotonically increasing order. This is to prevent Stream ID collisions even when the Client and Server create Streams at the same time. Stream IDs are not reused within a single Connection, and when IDs are exhausted (2^31), a new Connection is created to process subsequent RPCs.
  • gRPC RPCs are classified into the following four types according to the Message exchange pattern, and all types use a single Stream in the same way. The only differences are the number of Messages (DATA Frames) exchanged on the Stream and how long the Stream remains open, and Streaming RPCs keep a single Stream open for a long time while exchanging multiple Messages.
    • Unary RPC : The Client sends one Message and the Server responds with one Message. It is similar to a typical function call and is the most commonly used type.
    • Server Streaming RPC : When the Client sends one Message, the Server sends multiple Messages in succession. (e.g. real-time notification subscription, transmission of large query results)
    • Client Streaming RPC : The Client sends multiple Messages in succession, and then the Server responds with one Message. (e.g. File Upload, Metric transmission)
    • Bidirectional Streaming RPC : The Client and Server independently exchange multiple Messages on a single Stream. (e.g. chat)
  • Each Stream operates independently. Even if a specific RPC is canceled or an error occurs and the Stream is forcibly terminated with an RST_STREAM Frame, other RPCs on the same Connection are not affected.

1.2.2. Frame Structure and Trailer

HEADERS Frame            :status: 200
                         content-type: application/grpc
DATA Frame(s)            Length-Prefixed Message (5 Byte Prefix + ProtoBuf Message)
HEADERS Frame (Trailer)  grpc-status: 0
                         grpc-message: ...
[Text 2] Frame Structure of a gRPC Response

A single RPC (Stream) consists of a combination of HEADERS Frames and DATA Frames. A request starts with a HEADERS Frame containing the Method information (:path /<Package>.<Service>/<Method>) and the content-type: application/grpc Header, followed by DATA Frames containing ProtoBuf Messages. [Text 2] shows the Frame structure of a response, and the response ends with a Trailer containing the final processing result of the RPC (grpc-status, grpc-message) after the HEADERS Frame and DATA Frames.

A Trailer is a list of Fields in the same format as Headers (name-value pairs), and the only difference is its position: it is the last HEADERS Frame sent after the Body (DATA Frames). The reason gRPC sets the final processing result in the Trailer rather than at the beginning of the response is Streaming. In a Server Streaming RPC, an error can occur while the Server is sending multiple Messages, and since the first HEADERS Frame has already been sent at the start of the Stream, the final success of the RPC can only be determined after all Messages have been sent. In the case of an error response with no Messages to send, the Stream can also be terminated by setting grpc-status directly in the first HEADERS Frame without any DATA Frames, which is called a Trailers-Only response.

1.3. Status Code

Status CodeNumberDescription
OK0The request was processed successfully. Not an error.
CANCELLED1The operation was canceled. (Request canceled by the Client)
UNKNOWN2An error of unknown cause occurred. Debugging through detailed messages is required.
INVALID_ARGUMENT3The Client sent invalid request arguments.
DEADLINE_EXCEEDED4Request Timeout occurred. No response was received within the specified time.
NOT_FOUND5The requested Resource could not be found.
ALREADY_EXISTS6The requested Resource already exists. (Duplicate creation request)
PERMISSION_DENIED7Access denied due to insufficient permissions. (Authentication, Authorization failure)
RESOURCE_EXHAUSTED8Resource exhaustion such as capacity exceeded or out of memory. (The Client sent too many requests, or the Server received too many requests)
FAILED_PRECONDITION9Preconditions were not met. (Operation requested while a Lock is held)
ABORTED10The operation was aborted due to a concurrency conflict.
OUT_OF_RANGE11Request arguments exceeded the valid range. (Data type range exceeded)
UNIMPLEMENTED12The requested Method is not implemented on the Server.
INTERNAL13An error occurred inside the Server. Debugging is required.
UNAVAILABLE14The Server is down or unreachable. Retry is possible.
DATA_LOSS15Data loss occurred.
UNAUTHENTICATED16Authentication failed. Token is missing or invalid.
[Table 1] GRPC Status Code

[Table 1] shows the gRPC Status Codes. In gRPC, each RPC request determines its success through the Status Code returned in the response. The Status Code is delivered through the grpc-status Header in the Trailer that terminates the response Stream.

It is similar to the HTTP/2 Status Code but serves a different role. The gRPC Status Code is the result of each RPC request, while the HTTP/2 Status Code represents the result of Data transmission and routing from the HTTP/2 perspective. For example, if a Client calls a Method that does not exist on the Server through gRPC, the Status Code responds with UNIMPLEMENTED, but the HTTP/2 Status Code may respond with 200. This is because, from the HTTP/2 perspective, Data was exchanged successfully.

1.4. vs HTTP/1.1 + JSON

The biggest reason gRPC is currently attracting attention is that it is faster than the existing HTTP/1.1 + JSON Protocol. HTTP/1.1 and JSON are Text Protocols, which puts them at a disadvantage in terms of performance. HTTP/2 and ProtoBuf used by gRPC are Binary Protocols, so relatively fewer Packets are exchanged. In addition, gRPC further improves efficiency by using Connection Multiplexing and Server/Client Streaming supported by HTTP/2.

2. References