Building APIs with gRPC

Ratros Y.
Google Cloud - Community
4 min readFeb 25, 2019

This document discusses how to build a simple, one endpoint gRPC API service with Protocol Buffers, and prepare its client-side and server-side code with gRPC tools. It is a part of the Build API Services: A Beginner’s Guide tutorial series.

Note: This tutorial uses Python 3. gRPC, of course, supports a variety of programming languages.

About the API service

In this tutorial you will build an API service using gRPC where users can get their profiles. It has one resource, User, and one method (endpoint) only:

Before you begin

pip install grpcio grpcio-tools

grpcio is the gRPC package for Python. grpcio-tools, the gRPC tools package, includesProtocol Buffers compiler with gRPC plug-in.

Understanding the code

Essentially, an API call to a method (endpoint) is nothing more than an input (request), an output (response), and some magic that associates the request with the response. Input offers all the parameters the method requires, and output is what the method returns.

In an gRPC API service, inputs (requests) and outputs (responses) are Protocol Buffers messages of specific types, defined in one or more .proto files using Protocol Buffers language. Service definitions in the .proto files associate the input message type with the output message type, and Protocol Buffers compiler compiles the .proto file(s) into code artifacts. You may then use these artifacts to build your API service and its client libraries.

Resources and their fields

This gRPC API service features one resource: User.

The resource name of User is of the format //myapiservice.com/users/USER-ID. User features 3 fields:

Note that for simplicity reasons, Protocol Buffers does not have built-in support for reserved and required fields. All the fields are optional. Developers must validate the data themselves on the server side (and client side, if necessary)

Writing protocol buffers

example.proto (grpc/getting_started/example.proto) is the Protocol Buffers specification of this API service. It comprises 3 parts: syntax version, message types, and service definitions:

Syntax version

syntax = “proto3”;, declares the version of Protocol Buffers language (.proto file syntax) you would like to use. In most cases it is recommended that developers use version proto3; the default value is proto2.

Message types

The .proto file features two messages types: User and GetUserRequest. User has three string type fields: name, display_name, and email. GetUserRequest has one string type field, name.

The number after each field is the field number. Protocol Buffer messages use the field number, instead of the field name, to uniquely identify the field.

Service definition

The .proto file features one service definition, ExampleUserService, which consists of one method (endpoint), GetUser. It takes a message of the GetUserRequest type and returns another message of the User type.

Preparing the code

Protocol Buffers compiler can now prepare the server-end and the client-end artifacts:

python -m grpc_tools.protoc -I. --python_out=codegen/ --grpc_python_out=codegen/ example.proto

The compiler generates two files: codegen/example_pb2.py and codegen/example_pb2_grpc.py. example_pb2.py specifies how the message types in example.proto should look like in Python. example_pb2_grpc.py consists of two classes, ExampleServiceServicer and ExampleServiceStub, which you will use to build your own server-end and client-end code respectively.

Override ExampleServiceServicer to create your own gRPC API service, as showcased in server.py:

gRPC will invoke the overridden GetUser method in the ExampleServiceServicer class automatically when a client accesses the GetUser endpoint. The framework automatically parses the GetUserRequest Protocol Buffers message into a GetUserRequest Python class, which you can manipulate idiomatically; it then takes a User Python class, serializes it into a User Protocol Buffers message, and return it to the client. Note that both GetUserRequest and User Python classes are defined in example_pb2.py.

Next, use ExampleServiceStub to create a client for the gRPC API service, as showcased in client.py:

The client will connect to the gRPC API service automatically when running. When customers invoke the get_user method with a name parameter, you will prepare it into a GetUserRequest Python class, and pass it to gRPC via the stub. gRPC then parses the GetUserRequest Python class into a GetUserRequest Protocol Buffers message, and send it to the server; the response from the server, a User Protocol Buffers message, is then parsed into a User Python class, and printed out.

If helpful, think of the .proto file as a contract between the server and its clients, gRPC the courier, and Protocol Buffers the arbitrator/translator. Protocol Buffers enforces the contract, and translates what clients and server speak from/into a universal language, with gRPC carrying the communications around in HTTP/2. gRPC + Protocol Buffers perform all the administrative tasks behind the scenes (transportation, serialization, etc.) so your server and clients can focus on what is truly important: the business logic of your app.

Give it a Try

Run server.py in the background:

python server.py

The server listens at localhost:8080. Use the client to connect to the server; run the following Python script:

import client
client = client.ExampleServiceClient()
client.get_user(‘//myapiservice.com/users/1’)

You should see the following outputs:

User fetched.
name: “//myapiservice.com/users/1”
display_name: “Example User”
email: “user@example.com”

What’s next

See Building APIs with gRPC: Continued for recommended practices and patterns in gRPC API services.

--

--