Introduction to gRPC
Published in
4 min readDec 16, 2019
Introduction
- gRPC clients and servers can run and talk to each other in a variety of environments and can be written in any of gRPC’s supported languages
e.g. you can easily create a gRPC server in Java with clients in Go, Python, or Ruby. - define gRPC services in proto file
Install
$ pipenv install grpcio grpcio-tools
Example
- define gRPC service in .proto files.
// hello.protosyntax = "proto3";message HelloRequest { string value = 1;}message HelloResponse { string value = 1;}service Hello { rpc Hello(HelloRequest) returns (HelloResponse) {}}$ pipenv run python -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. hello.proto// generate hello_pb2.py & hello_pb2_grpc.py, define message class and service class respectively
- gRPC uses protoc with special gRPC plugin to get generated gRPC client and server code
Server.py
- The server implements the methods declared by the service and runs a gRPC server to handle client calls. The gRPC infrastructure decodes incoming requests, executes service methods, and encodes service responses.
#server.pyfrom concurrent import futuresimport timeimport grpcimport hello_pb2, hello_pb2_grpcclass HelloServicer(hello_pb2_grpc.HelloServicer): def Hello(self, request, context): response = hello_pb2.HelloResponse() response.value = f"Hello {request.value}" return response
def serve(): server = grpc.server(futures.ThreadPoolExecutor(max_workers=10)) hello_pb2_grpc.add_HelloServicer_to_server(HelloServicer(), server) server.add_insecure_port('[::]:50051') server.start() try: while True: time.sleep(86400) except KeyboardInterrupt: server.stop(0)
if __name__ == '__main__': serve()
client.py
# client.pyimport grpcimport hello_pb2import hello_pb2_grpcchannel = grpc.insecure_channel('localhost:50051')stub = hello_pb2_grpc.HelloStub(channel) # create a gRPC clientrequest = hello_pb2.HelloRequest(value="World") # create a request response = stub.Hello(request) # call Hello service, return HelloResponseprint(response.value) # "Hello World"
Types of RPC
- Unary RPCs
The client sends a single request to the server and gets a single response back, just like a normal function call. - Server-side streaming RPC
The client sends a request to the server and gets a stream to read a sequence of messages back. The client reads from the returned stream until there are no more messages. - Client-side streaming RPC
The client writes a sequence of messages and sends them to the server, again using a provided stream. Once the client has finished writing the messages, it waits for the server to read them and return its response. - Bidirectional streaming RPC
Both sides send a sequence of messages using a read-write stream. The two streams operate independently, so clients and servers can read and write at the same time.
service StreamService { // Unary
rpc SayHello(HelloRequest) returns (HelloResponse){};
// Server Streaming
rpc LotsOfReplies(HelloRequest) returns (stream HelloResponse) {}; // Client Streaming
rpc LotsOfGreetings(stream HelloRequest) returns (HelloResponse) {}; // Bidirectional streaming
rpc BidiHello(stream HelloRequest) returns (stream HelloResponse) {};}
gRPC-web
- gRPC-Web is an auxiliary protocol providing a translation layer between browser requests and gRPC.
- Goal: Provide gRPC access to browser client
- current limitations: unary calls and server streaming only
Install
$ npm install grpc-web
Steps:
- define gRPC service in .proto files.
syntax = "proto3";package helloworld;service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply);
}message HelloRequest {
string name = 1;
}message HelloReply {
string message = 1;
}
2. Implement gRPC backend server
// server.jsvar PROTO_PATH = __dirname + '/helloworld.proto';
var grpc = require('grpc');
var protoLoader = require('@grpc/proto-loader');
var packageDefinition = protoLoader.loadSync(
PROTO_PATH,
{keepCase: true,
longs: String,
enums: String,
defaults: true,
oneofs: true
});
var protoDescriptor = grpc.loadPackageDefinition(packageDefinition);
var helloworld = protoDescriptor.helloworld;
function doSayHello(call, callback) {
callback(null, {
message: 'Hello! ' + call.request.name
});
}
function getServer() {
var server = new grpc.Server();
server.addService(helloworld.Greeter.service, {
sayHello: doSayHello,
});
return server;
}
if (require.main === module) {
var server = getServer();
server.bind('0.0.0.0:9090', grpc.ServerCredentials.createInsecure());
server.start();
}
exports.getServer = getServer;
3. Configure the Envoy Proxy (envoy.yaml)
Envoy
- client calls need to be translated into gRPC-friendly calls, and the role is now filled by Envoy.
- Envoy translates the HTTP/1.1 calls produced by the client into HTTP/2 calls that can be handled by those services (gRPC uses HTTP/2 for transport)
- In general this is a pretty standard HTTP configuration for Envoy. There are just a few small differences:
1.x-grpc-web
,grpc-status
, andgrpc-message
in headers
2. http_filters: — name:envoy.grpc_web
4. Generate client code using the protocol buffer compiler.
$ protoc -I=. helloworld.proto \
--js_out=import_style=commonjs:. \
--grpc-web_out=import_style=commonjs,mode=grpcwebtext:.
generate helloworld_pb.js and helloworld_grpc_web_pb.js
5. Use the gRPC-Web API to write a simple client for your service.
//client.jsconst {HelloRequest, HelloReply} = require('./helloworld_pb.js');
const {GreeterClient} = require('./helloworld_grpc_web_pb.js');var client = new GreeterClient('http://localhost:8080');
var request = new HelloRequest();
request.setName('World');
client.sayHello(request, {}, (err, response) => {
console.log(response.getMessage());
});
6. compile the client javascript code
$ npm install
$ npx webpack client.js
Then, open up the developer console and you should see the following printed out:
Hello! World
Reference
- https://grpc.io/docs/guides/
- https://medium.com/@penolove15/%E8%AD%AF-grpc-basics-python-8bde8bbb4486
- https://codinganimal.info/grpc-tutorial-for-python-2fa0fe2ff853
- https://yami.io/grpc/
- https://www.youtube.com/watch?v=pzxy25ho5WY
- https://github.com/grpc/grpc-web/tree/master/net/grpc/gateway/examples/helloworld
- https://www.youtube.com/watch?v=RtyKEDZipsM
- https://blog.envoyproxy.io/envoy-and-grpc-web-a-fresh-new-alternative-to-rest-6504ce7eb880