Google recently released gRPC as open source, an efficient framework for remote procedure calls (RPC) that uses a variety of programming languages.
RPCs, which are a common method of communication between servers, are not new. They date back to the 1980s, and because of their server-side nature, they are usually not exposed to most computer users, and not even to most software developers. Given that the RPCs role is to support communications between computer servers, they are mostly visible to system administrators and DevOps. That said, their importance is fundamental, given that they are the standard mechanism to connect the many distributed systems that carry a very large fraction of Internet traffic.
Image of Wikipedia servers
gRPC is based on the recently finalized HTTP/2 standard that enables new capabilities such as:
- Bidirectional streaming
- Flow control
- Header compression
- Multiplexing requests over a single TCP connection
gRPC provides libraries for multiple languages, including:
- C
- C++
- Java
- Go
- Node.js
- Python
- Ruby
The source code of gRPC can be found on GitHub, which includes extensive documentation and a main webpage. The release of gRPC is synchronized with a new release of Protocol Buffers: proto3. Protocol buffers are used to:
- Specify the content and structure of messages exchanged between servers
- Serialize and deserialize the messages
- Generate source code for objects in multiple languages that read and write messages
- Provide a mechanism for versioning the message definitions, so that clients and servers with different versions can still interoperate
Show me gRPC
The Quick Start guide has a summary of Hello World in Python. It defines a service to which you (the client) send your name, i.e. “John Doe”, and the service replies with the composed string: "Hello, John Doe”.
Here are the messages that will go through the wire:
// The request message containing the user's name.
message HelloRequest { optional string name = 1; }
// The response message containing the greetings.
message HelloReply { optional string message = 1; }
And here is the service definition:
syntax = "proto2";
// The greeting service definition.
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
If we put this service and messages definition in a file helloworld.proto and process it with the Proto3 compiler, it will generate Python code for both the client side and the server side.
The client side will look like:
import helloworld_pb2
_TIMEOUT_SECONDS = 10
def run():
with helloworld_pb2.early_adopter_create_Greeter_stub('localhost', 50051) as stub:
response = stub.SayHello(helloworld_pb2.HelloRequest(name='you'), _TIMEOUT_SECONDS)
print "Greeter client received: " + response.message
if __name__ == '__main__':
run()
And the server side will look like:
import time
import helloworld_pb2
_ONE_DAY_IN_SECONDS = 60 * 60 * 24
class Greeter(helloworld_pb2.EarlyAdopterGreeterServicer):
def SayHello(self, request, context):
return helloworld_pb2.HelloReply(message='Hello, %s!' % request.name)
def serve():
server = helloworld_pb2.early_adopter_create_Greeter_server(Greeter(), 50051, None, None)
server.start()
try:
while True:
time.sleep(_ONE_DAY_IN_SECONDS)
except KeyboardInterrupt:
server.stop()
if __name__ == '__main__':
serve()
More details are available in the starting guide.
Disclaimer: The indentation in the Python code above are not exact. For proper and correct Python syntax, please follow the links provided.
1 Comment