gRPC Unary RPC — Synchronous Request-Response Communication
In this tutorial, you will learn about grpc unary rpc. We cover key concepts, practical examples, and best practices to help you master this topic.
Unary RPC is the simplest gRPC pattern — a single request message from the client elicits a single response message from the server, similar to a REST API call.
What You'll Learn
You will learn how to implement unary RPCs on server and client, handle errors, set deadlines, and follow best practices for synchronous gRPC communication.
Unary RPC Definition
service DeviceService {
rpc GetDevice(GetDeviceRequest) returns (Device);
rpc CreateDevice(CreateDeviceRequest) returns (Device);
rpc UpdateDevice(UpdateDeviceRequest) returns (Device);
rpc DeleteDevice(DeleteDeviceRequest) returns (DeleteDeviceResponse);
}
message GetDeviceRequest { string id = 1; }
message CreateDeviceRequest {
string name = 1;
string os = 2;
string user_id = 3;
}
Server Implementation
class DeviceServiceServicer(device_pb2_grpc.DeviceServiceServicer):
def GetDevice(self, request, context):
device = db.get_device(request.id)
if not device:
context.abort(grpc.StatusCode.NOT_FOUND, f"Device {request.id} not found")
return device_pb2.Device(
id=device.id,
name=device.name,
os=device.os,
status=device_pb2.ONLINE,
)
def CreateDevice(self, request, context):
if not request.name or not request.os:
context.abort(grpc.StatusCode.INVALID_ARGUMENT, "name and os required")
device = db.create_device(name=request.name, os=request.os, user_id=request.user_id)
return device_pb2.Device(
id=device.id,
name=device.name,
os=device.os,
)
Client Implementation
import grpc
import device_pb2
import device_pb2_grpc
def run():
channel = grpc.insecure_channel("localhost:50051")
stub = device_pb2_grpc.DeviceServiceStub(channel)
# Simple call
device = stub.GetDevice(device_pb2.GetDeviceRequest(id="dev-001"))
print(f"Device: {device.name} ({device.os})")
# Call with deadline
try:
device = stub.GetDevice(
device_pb2.GetDeviceRequest(id="dev-001"),
timeout=5.0 # 5 second deadline
)
except grpc.RpcError as e:
print(f"gRPC error: {e.code().name} — {e.details()}")
# Create device
new_device = stub.CreateDevice(
device_pb2.CreateDeviceRequest(name="Office-PC", os="Windows 11", user_id="user-001")
)
print(f"Created: {new_device.id}")
if __name__ == "__main__":
run()
Common Mistakes
1. Not Handling gRPC Status Codes
Always catch grpc.RpcError and check e.code(). Different codes need different handling (NOT_FOUND, UNAVAILABLE, DEADLINE_EXCEEDED).
2. No Timeouts on Client Calls
Without timeouts, a stuck server holds client resources indefinitely. Always set timeout on client calls.
3. Blocking in Server Handlers
Long-running operations in unary handlers block the thread pool. Use async handlers or offload to worker threads.
4. Returning Wrong Status Codes
Validation errors should return INVALID_ARGUMENT. Missing resources return NOT_FOUND. Use the correct gRPC status code.
5. Not Validating Input
Client requests may contain invalid data. Always validate input in server handlers before processing.
Practice Questions
- What is a unary RPC?
- How do you set a deadline on a client call?
- How do you return errors from a server handler?
- What status code should you use for invalid input?
- Why should you validate input in server handlers?
Answers:
- A unary RPC is a single request followed by a single response — the simplest gRPC pattern, analogous to HTTP request-response.
- Pass
timeout=secondsto the stub method or set adeadlineon the channel. - Call
context.abort(grpc.StatusCode, "message")or return an error from the handler. INVALID_ARGUMENTfor invalid input,NOT_FOUNDfor missing resources,UNAUTHENTICATEDfor auth failures.- Clients may send invalid or malicious data. Always validate at the server boundary regardless of client-side validation.
Mini Project
Build a unary gRPC service for DodaTech's device management. Include GetDevice, CreateDevice, UpdateDevice, and DeleteDevice with proper error handling, input validation, and client timeouts.
What's Next
| Topic | Description |
|---|---|
| Server Streaming | One request, stream of responses |
| Client Streaming | Stream of requests, one response |
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro