Implementing gRPC Communication

1. Defining Protocol Buffers

ElementSyntax
Syntax versionsyntax = "proto3";
Packagepackage shop.v1;
Messagemessage Order { string id = 1; }
Field typesscalar (int32, string, bool), message, enum, map, repeated
Serviceservice OrderService { rpc Get(GetReq) returns (Order); }
Field numbers1–15: 1-byte tag (use for hot fields); never reuse
Reservedreserved 4, 5; reserved "old_name";

Example: order.proto

syntax = "proto3";
package shop.v1;

service OrderService {
  rpc Get(GetOrderRequest) returns (Order);
  rpc List(ListOrdersRequest) returns (stream Order);
  rpc Bulk(stream CreateOrder) returns (BulkResult);
  rpc Chat(stream Event) returns (stream Event);
}

message GetOrderRequest { string id = 1; }
message Order { string id = 1; double total = 2; OrderStatus status = 3; }
enum OrderStatus { DRAFT = 0; PAID = 1; SHIPPED = 2; }

2. Generating Service Stubs

LanguageTool
Javaprotoc --java_out --grpc-java_out or Gradle plugin
Goprotoc-gen-go + protoc-gen-go-grpc
Node/TS@grpc/proto-loader or ts-proto
Pythongrpcio-tools
Modernbuf generate with buf.gen.yaml

3. Implementing Unary RPCs

Example: Unary server (Java)

public class OrderImpl extends OrderServiceGrpc.OrderServiceImplBase {
  @Override public void get(GetOrderRequest req, StreamObserver<Order> out) {
    Order o = repo.find(req.getId())
        .orElseThrow(() -> Status.NOT_FOUND.withDescription("order").asRuntimeException());
    out.onNext(o);
    out.onCompleted();
  }
}
RPC StylePattern
Unary1 request → 1 response
WhenCRUD, auth, simple lookups

4. Implementing Server Streaming

Use CaseExample
Large listsStream rows, bounded memory
Live feedsStock prices, telemetry
BackpressureUse ServerCallStreamObserver.isReady()

5. Implementing Client Streaming

Use CaseExample
Bulk uploadsStream events; one summary back
AggregationsCompute over long input stream
Flow controlServer signals readiness

6. Implementing Bidirectional Streaming

Use CaseExample
Chat / collabIndependent send/recv
Real-time syncState diff streams both ways
Order independenceFrames interleave freely

7. Using gRPC Metadata

Metadata KeyUse
authorizationBearer token
x-request-idCorrelation ID
grpc-timeoutAuto-set from withDeadline
-bin suffixBinary metadata: trace-bin

8. Handling gRPC Errors

Status CodeMaps To
OK (0)Success
CANCELLED (1)Client cancelled
INVALID_ARGUMENT (3)HTTP 400
DEADLINE_EXCEEDED (4)HTTP 504
NOT_FOUND (5)HTTP 404
ALREADY_EXISTS (6)HTTP 409
PERMISSION_DENIED (7)HTTP 403
RESOURCE_EXHAUSTED (8)HTTP 429
FAILED_PRECONDITION (9)HTTP 412
UNAUTHENTICATED (16)HTTP 401
UNAVAILABLE (14)HTTP 503; safe to retry
INTERNAL (13)HTTP 500
Note: Use google.rpc.Status with ErrorInfo/BadRequest details for structured errors.

9. Implementing Deadlines and Timeouts

ConceptDetail
Deadline (absolute)Set by client; propagates across services
Timeout (relative)Client sugar: withDeadlineAfter(2, SECONDS)
Server checkContext.current().getDeadline() to abort early
PropagationReduces remaining budget down the call chain

10. Using gRPC Interceptors

InterceptorPurpose
AuthValidate token, populate Context
LoggingMethod, latency, status
TracingOpenTelemetry spans
MetricsPrometheus RED metrics
Retry/HedgingClient-side

11. Implementing Load Balancing

ModeDetail
pick_firstDefault; one connection
round_robinDistributes RPCs evenly across subchannels
xDSEnvoy/proxyless service mesh policies
Name resolverDNS, Consul, Kubernetes headless service
Server-sideL7 proxy (Envoy) terminates HTTP/2 frames

12. Managing Protocol Buffer Versioning

RuleWhy
Never reuse field numbersWire format depends on tag
Don't change typesDecoders may misread bytes
Add new fields with defaultsOld clients ignore them
reserved removed fieldsPrevent accidental reuse
Version packageshop.v1, shop.v2 for breaking changes
Use Bufbuf breaking against last release