What is the gRPC

GRPC is a high-performance, universal open source RPC framework developed by Google. It is mainly developed for mobile applications and designed based on THE HTTP/2 Protocol standard. It is developed based on the Protocol Buffers (Protobuf) serialization Protocol and supports many development languages. In gRPC, a client can directly invoke the methods of server applications on different machines as if using a local object. This makes it easier to build distributed applications and services. Like other RPC systems, gRPC is based on defining a service, specifying the methods that the service can be called remotely, and their parameters and return types. On the server side, the interface that implements the service then runs a gRPC service to handle the outgoing requests. On the client side, the client has a stub (a stub is just a client in some languages) that provides the same methods as the server.

·gRPC clients and servers can run in a variety of environments and communicate with each other, and can be written in any language supported by gRPC. So, for example, you can easily create gRPC servers in Java using Go, Python, or Ruby clients. In addition, the interface to the latest Google API will have a gRPC version, making it easy to build Google functionality into your applications.

Using the protocol buffer

By default, gRPC uses the Protocol Buffer, which is used to serialize structured data (although it can be used with other data formats, such as JSON). The first step in using the protocol buffer is to define the structure for the data to be serialized in a proto file: a plain text file with a. Proto file extension. Protocol Buffer data is constructed as messages, where each message is a logical record of the information, containing a series of name/value pairs called fields. Here’s a simple example:

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

Once you have defined the data structure, you can use the Protocol Buffer compiler Protoc to generate data access classes for your language of choice. Access classes provide simple accessors for each field (for example, name()) and set_name()), as well as a way to serialize the entire structure to raw bytes or parse the entire structure out of raw bytes – for example, if your language of choice is C ++, a class named Person is generated in the example above. You can then use this class in your application to populate, serialize, and retrieve The Protocol Buffer messages for Person.

In addition, you define the gRPC service in the.proto file and specify the RPC method parameters and return type as protocol Buffer messages:

// The greeter service definition.
service Greeter {
  // Sends a greeting
  rpc SayHello (HelloRequest) returns (HelloReply) {}
}

// The request message containing the user's name. message HelloRequest { string name = 1; } // The response message containing the greetings message HelloReply { string message = 1; }Copy the code

The use of gRPC also uses the compiler protoc to generate code from proto files, but the compiler first installs a gRPC plug-in. Using the gRPC plug-in, you can get generated gRPC client and server code, as well as code for the general Protocol Buffer access classes used to populate, serialize, and retrieve message types.

Some of the key concepts in gRPC are described in more detail below.

The service definition

Like many RPC systems, gRPC revolves around the idea of defining a service, specifying methods that can be called remotely with their arguments and return types. By default, gRPC uses the Protocol Buffer as an interface definition language (IDL) to describe the structure of the service interface and payload messages. Alternative methods can be used if needed.

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

message HelloRequest {
  string greeting = 1;
}

message HelloResponse {
  string reply = 1;
}
Copy the code

GRPC allows you to define four service methods:

  • Unary RPC, where the client sends a single request to the server and gets a single response, just like a normal function call.
rpc SayHello(HelloRequest) returns (HelloResponse){
}
Copy the code
  • Server-side streaming RPC, where a client sends a request to the server and fetches a stream to read and retrieve a series of messages. The client reads from the returned stream until there are no more messages. GRPC guarantees the order of messages in a single RPC call.
rpc LotsOfReplies(HelloRequest) returns (stream HelloResponse){
}
Copy the code
  • Client-side streaming RPC, where the client uses the provided stream to write sequences of messages and then send them to the server. After the client finishes writing the message, it waits for the server to read the message and return a response. GRPC ensures the order of messages in a single RPC call.
rpc LotsOfGreetings(stream HelloRequest) returns (HelloResponse) {
}
Copy the code
  • Two-way streaming RPC, in which both parties send a series of messages using a read/write stream. The two flows run independently, so the client and server can read and write in whatever order they prefer: for example, the server can wait to receive all client messages before writing a response, or it can read one message and then write another, or some other read and write combination. The order of messages in each flow is preserved.
rpc BidiHello(stream HelloRequest) returns (stream HelloResponse){
}
Copy the code

We’ll compare these different RPCS in more detail in the RPC Life cycle section below.

Using the API Interface

Starting with the service definition in the.proto file, gRPC provides a Protocol Buffer compiler plug-in that generates client-side and server-side code. GRPC users typically invoke these apis on the client side and implement the corresponding apis on the server side.

  • On the service side, the server implements the methods declared in the service and runs a gRPC server to handle client calls. The gRPC infrastructure decodes incoming requests, executes the methods of the service, and encodes the response of the service.
  • On the client side, the client has a local object called a stub(some languages prefer to call a stub a client) that also implements the methods in the service. The client can call these methods only on the local object, wrapping the call parameters in the appropriate Protocol Buffer message type, and gRPC takes care of sending the request to the server and returning the protocol Buffer response to the server.

Synchronous vs Asynchronous

Synchronous RPC calls block the current thread until the server receives the response, which is the closest approximation to the procedure call abstraction that RPC seeks. On the other hand, the network is asynchronous in nature, and in many cases it is useful to be able to start RPC without blocking the current thread.

GRPC programming interfaces in most languages come in both synchronous and asynchronous forms. More information can be found in tutorials and reference documentation for each language.

RPC life cycle

Now let’s look specifically at what happens when a gRPC client calls a gRPC server’s method. We won’t look at the implementation details until a later programming language tutorial.

One yuan RPC

Let’s start with the simplest RPC type, where the client sends a request and receives a response.

  • Once a client calls a method on the stub/client object, the server is notified that the RPC has been called, and also receives client-side metadata at the time of the call, the name of the method called, and the specified cut-off time (if applicable).
  • The server can then send its own initial metadata immediately (it must be sent before any response is sent), or it can wait for the client’s request message – whichever comes first, as specified by the application.
  • Once the server receives the customer’s request message, it does the necessary work to create and populate its response. The response, if successful, is then returned along with the status details (status codes and optional status messages) and optional trailing metadata.
  • If the status is OK, the client gets the response, which completes and terminates the call on the client side.

Server streaming RPC

A server-side streaming RPC is similar to simple unary RPC, except that the server sends back a response flow when it receives a request message from the client. After all responses are sent back, the server’s status details (status codes and optional status information) and optional trailing metadata are sent back to complete the server’s work. The client completes the operation after receiving all the server responses.

Client-side streaming RPC

Client-side streaming RPC is also similar to unary PRC, except that the client sends a stream of requests to the server instead of a single request. The server typically (but not necessarily) sends a single response after receiving all requests from the client, along with its status details and optional trailing metadata.

Two-way streaming RPC

In two-way streaming RPC, the call is again initiated by the client-calling method, and the server receives client-side metadata, method name, and duration. Again, the server can choose to send back its initial metadata or wait for the client to start sending the request.

What happens next depends on the application, because the client and server can read and write in any order — streaming operations run completely independently. So, for example, the server can wait until it receives all of the client’s messages before writing a response, or the server and client can play “ping pong” : the server receives a request, sends back a response, the client sends another request based on the response, and so on.

End time/Timeout time

GRPC allows a client to specify how long it is willing to wait for the RPC to complete its work before it is terminated by the DEADLINE_EXCEEDED error. On the server side, the server can see if a particular RPC has timed out or how much time is left to complete the RPC.

How you specify a deadline or timeout varies from language to language – for example, not all languages have a default deadline, and some language apis work by deadline (a fixed point in time), while others work by timeout (duration).

RPC termination

In gRPC, the client and the server make independent, locally based decisions about the success of the call, and the conclusions on both sides may not match. This means, for example, that you might have an RPC that completed successfully on the server side (” I sent all responses “) but failed on the client side (” The response arrived after the deadline I specified “). It is also possible for the server to decide that the RPC is complete before the client sends all requests.

Cancel the RPC

Either a client or a server can cancel RPC at any time. The cancel operation terminates the RPC immediately, so no more work is done. This is not “undo” : changes made before you cancel are not rolled back.

metadata

Metadata is information about a particular RPC call (such as authentication details) in the form of a key-value pair list, where keys are strings and values are generally strings (but can also be binary data). Metadata is opaque to the gRPC itself – it allows clients to provide invocation-related information to the server, and vice versa.

Access to metadata depends on the language.

channel

A gRPC channel provides a connection to a gRPC server with a specified host and port number, and is used when creating client stubs (or “clients” for some languages). The client can specify channel parameters to change the default behavior of gRPC, such as turning on/off message compression. Each channel has states, including Connected and idle.

How the gRPC handles closed channels is language-dependent, and some languages allow you to query channel status.