gRPC
gRPC fundamentals, Protocol Buffers, grpcurl CLI, and Python implementation.
gRPC Fundamentals
gRPC vs REST — when to choose each
Aspect gRPC REST Protocol HTTP/2 (binary, multiplexed) HTTP/1.1 or HTTP/2 (text) Format Protocol Buffers (binary) JSON (text) Streaming Bidirectional, server, client Request-response only Performance ~10x faster serialization Human-readable, debuggable Contract .proto file (strict) OpenAPI (optional) Browser Needs gRPC-Web proxy Native When to use Microservice-to-microservice Client-facing APIs, CRUD
Protocol Buffers
Define a service and messages — .proto file
syntax = "proto3";
package devices;
service DeviceService {
rpc GetDevice (DeviceRequest) returns (DeviceResponse);
rpc ListDevices (ListRequest) returns (stream DeviceResponse);
rpc UpdateDevice (DeviceUpdate) returns (DeviceResponse);
}
message DeviceRequest {
string device_id = 1;
}
message DeviceResponse {
string id = 1;
string name = 2;
string ip = 3;
int32 vlan = 4;
string status = 5;
}
message ListRequest {
int32 page_size = 1;
string page_token = 2;
}
message DeviceUpdate {
string id = 1;
string name = 2;
int32 vlan = 3;
}
Compile proto to Python
pip install grpcio grpcio-tools
python -m grpc_tools.protoc \
-I./protos \
--python_out=./generated \
--grpc_python_out=./generated \
protos/devices.proto
grpcurl — CLI for gRPC (like curl for REST)
Install grpcurl
# Arch
pacman -S grpcurl
# Go install
go install github.com/fullstorydev/grpcurl/cmd/grpcurl@latest
List services — gRPC reflection (like OpenAPI for gRPC)
grpcurl -plaintext localhost:50051 list
# devices.DeviceService
Describe a service — show available RPCs
grpcurl -plaintext localhost:50051 describe devices.DeviceService
Call a unary RPC — request/response
grpcurl -plaintext \
-d '{"device_id": "42"}' \
localhost:50051 devices.DeviceService/GetDevice
Call with TLS
grpcurl -cacert ca.pem -cert client.pem -key client.key \
-d '{"device_id": "42"}' \
api.example.com:443 devices.DeviceService/GetDevice
Python gRPC Client
Unary call — simple request/response
import grpc
import devices_pb2
import devices_pb2_grpc
channel = grpc.insecure_channel("localhost:50051")
stub = devices_pb2_grpc.DeviceServiceStub(channel)
request = devices_pb2.DeviceRequest(device_id="42")
response = stub.GetDevice(request)
print(f"{response.name} ({response.ip}) VLAN {response.vlan}")
Server streaming — receive multiple responses
request = devices_pb2.ListRequest(page_size=100)
for device in stub.ListDevices(request):
print(f"{device.name}: {device.status}")
Secure channel with TLS
with open("ca.pem", "rb") as f:
ca_cert = f.read()
credentials = grpc.ssl_channel_credentials(ca_cert)
channel = grpc.secure_channel("api.example.com:443", credentials)
Python gRPC Server
Implement a service
import grpc
from concurrent import futures
import devices_pb2
import devices_pb2_grpc
class DeviceServicer(devices_pb2_grpc.DeviceServiceServicer):
def GetDevice(self, request, context):
# Look up device by ID
return devices_pb2.DeviceResponse(
id=request.device_id,
name="sw-core-01",
ip="10.50.1.100",
vlan=10,
status="active",
)
def ListDevices(self, request, context):
for device in all_devices[:request.page_size]:
yield devices_pb2.DeviceResponse(**device)
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
devices_pb2_grpc.add_DeviceServiceServicer_to_server(DeviceServicer(), server)
server.add_insecure_port("[::]:50051")
server.start()
server.wait_for_termination()
Streaming Patterns
Four RPC types
Type Client sends Server sends Use case Unary 1 message 1 message Simple lookup Server streaming 1 message N messages Live logs, event feed Client streaming N messages 1 message File upload, batch Bidirectional N messages N messages Chat, real-time sync
Health Checking
gRPC health check protocol — standard for load balancers
grpcurl -plaintext localhost:50051 grpc.health.v1.Health/Check
# {"status": "SERVING"}
Relevance
gRPC appears in Cisco network automation (gNMI for telemetry, gNOI for operations) and increasingly in microservice architectures. The grpcurl tool is the gRPC equivalent of curl — essential for debugging without writing client code.