No description
Find a file
2025-09-23 16:06:31 +02:00
README.md Update README.md 2025-09-23 16:06:31 +02:00

gRPC

gRPC is a non-plain-text remote procedure call protocol and framework that favor efficiency at the expense of programmer-legibility.

So, for example, while gRPC + protobuf are less legible (to programmers) than (plain) HTTP + JSON, gRPC + protobuf is more efficient than (plain) HTTP + JSON.

Name

The "RPC" in "gRPC" is short for "Remote Procedure Calls". The "g" in "gRPC" is probably short for "Google" — although it seems to be discouraged to mention that.

Protocol Buffers

Protocol Buffers, often shortened to protobuf or protobufs, is a non-plain-text serialization format comparable to JSON and (back-in-the-day) XML.

Protocol Buffers is usually used in combination with gRPC.

HTTP Paths

gRPC servers do not directly make use of the HTTP path in the way that traditional RESTful web servers do.

The gRPC server itself is designed around RPC method calls defined in .proto files, not HTTP URL paths. The HTTP path becomes relevant only when bridging gRPC with other protocols or systems that rely on them.

Protocol Buffers and Method Names

gRPC uses Protocol Buffers (protobuf) (i.e., .proto files) to define services and their methods. When a client makes a gRPC call, it specifies the fully qualified method name, which is structured as /package.Service/Method. For example, /helloworld.Greeter/SayHello. This method name is part of the gRPC request's metadata, not a URL path.

HTTP/2 as a Transport Layer

While gRPC runs over HTTP/2, it abstracts away the HTTP details. HTTP/2 is used for its performance benefits, such as multiplexing, header compression, and bidirectional streaming. The actual RPC method being called is encoded within the HTTP/2 frames, not directly mapped to HTTP URL paths.

gRPC-Aware Proxies and Gateways

If you need to expose gRPC services to systems that expect HTTP (like web browsers or REST clients), you'd typically use a gRPC-aware proxy or a gRPC-to-HTTP gateway (like gRPC-Gateway). These intermediary components translate between gRPC requests and HTTP requests, and they would be the ones interpreting HTTP paths and mapping them to gRPC services and methods.

grpcurl

There is a command-line tool called grpcurl that is similar to curl but for gRPC.

grpcurl is a command-line tool for interacting with gRPC APIs, much like curl is for HTTP.

It allows you to discover services, inspect their methods and messages, and send requests without needing to write any client code.

Here is how one might typically use grpcurl to test a gRPC endpoint:

1. Listing Services

Before you can call a method, you need to know what services and methods are available. If your gRPC server supports server reflection (which is highly recommended for discoverability), you can list them:

grpcurl [flags] <server_address> list
  • [flags]: Common flags include:
    • -plaintext: Use an insecure, unencrypted connection (useful for local development).
    • -insecure: Similar to -plaintext, but specifically for skipping TLS verification.
    • -proto <file>: Specify a .proto file if the server doesn't support reflection.
    • -import-path <dir>: Directory containing .proto files.
  • <server_address>: This is the address of your gRPC server, e.g., localhost:50051 or my-grpc-service.example.com:443.

For example, to list all services on a local server running on port 50051:

grpcurl -plaintext localhost:50051 list

This will output a list of services, typically in the format package.ServiceName.

2. Describing Services and Methods

Once you know the service name, you can get more details about it, including its methods and the structure of its request and response messages.

grpcurl [flags] <server_address> describe <service_name>

For example, to describe the helloworld.Greeter service:

grpcurl -plaintext localhost:50051 describe helloworld.Greeter

This will show you the RPC methods available within that service, their request types, and their response types.

You can also describe specific messages:

grpcurl -plaintext localhost:50051 describe helloworld.HelloRequest

3. Invoking RPC Methods

This is where you actually send requests to your gRPC endpoint.

grpcurl [flags] -d '<JSON_payload>' <server_address> <service.Method>
  • -d '<JSON_payload>': The data for your request, formatted as a JSON string. This corresponds to the request message defined in your .proto file.
  • <service.Method>: The fully qualified name of the gRPC method you want to call, ex: helloworld.Greeter.SayHello.

For example, to call the SayHello method of the helloworld.Greeter service with a JSON payload:

grpcurl -plaintext -d '{"name": "Alice"}' localhost:50051 helloworld.Greeter/SayHello

The output will be the response from the server, also in JSON format by default.

Handling Different RPC Types

grpcurl also supports:

  • Server-Streaming: You'll see multiple messages printed as they are received.
  • Client-Streaming: You can provide multiple JSON objects to stdin or a file, separated by newlines.
  • Bidirectional Streaming: Interactive mode allows you to send messages and receive responses in real-time.

Example Scenario: A Simple Greeter Service

// greeter.proto
syntax = "proto3";

package helloworld;

service Greeter {
  rpc SayHello (HelloRequest) returns (HelloReply);
}

message HelloRequest {
  string name = 1;
}

message HelloReply {
  string message = 1;
}

And it's running on localhost:50051.

1. List services:

grpcurl -plaintext localhost:50051 list

The output might be similar to:

helloworld.Greeter
grpc.reflection.v1alpha.ServerReflection

2. Describe the service and request message:

grpcurl -plaintext localhost:50051 describe helloworld.Greeter
grpcurl -plaintext localhost:50051 describe helloworld.HelloRequest

The output from describe helloworld.Greeter might look similar to:

service Greeter {
  rpc SayHello ( .helloworld.HelloRequest ) returns ( .helloworld.HelloReply );
}

And, the output from describe helloworld.HelloRequest might look similar to:

message HelloRequest {
  string name = 1;
}

3. Call the SayHello method:

grpcurl -plaintext -d '{"name": "World"}' localhost:50051 helloworld.Greeter/SayHello

Output:

{
  "message": "Hello World"
}