gRpc beginner guide1: gRpc 101
Preface
I bet you’ve heard people talking about RPC, gRPC all the time. You may already got questions like: What are they, why we need them in my system? seems like the RESTful API works just fine for us. How I should implement it, hope will not be too complicated.
In this WHAT/WHY/HOW style blog, I am gonna first illustrate some key about RPC/gRPC, and then show how gRPC works by a simple example, hope you enjoy it.
What is RPC/gRPC
Some of you may know RPC is stand for Remote Procedure Call, it’s a mechanism to communicate between processes, which enable programmer to invoke procedures(functions) reside on remote computer, but code just quite as simple as calling local functions.
That make our life much easier, right? Because in our code, we do not need to worry about the network programming details, just call a local object’s method(which is a proxy of remote service, called stub) with some input parameters, and get result back, like calling the local functions!
What is gRpc anyway? It’s an implementation of RPC mechanism, or we can say it’s an concrete object of RPC class. The initial g may come from Google who invented it.
Why we need gRPC
Why we need RPC? As discussed, RPC made our day easier because it handles a lot of networking communication details, which make access of remote service just like local function call. I agree with the metaphore that in a microservice system, each service is indispensable part of human body, RPC is like veins/neural connecting them.
Why we choose gRPC? gRPC use protobuf to transmit data, much faster; And gRPC is quite powerful and versatile: it is built on HTTP/2: so proxies, firewalls and streaming reside in gRPC nature; gRPC integrates seamlessly with ecosystem components like service discovery, name resolver, load balancer, tracing and monitoring.
How we use gRpc in Golang
Setup protobuf environment
As I wrote in here, you need to set up your protobuf environment first, gRPC use protobuf to transfer data
in summary, you need to:
1 | # Make sure you grab the latest version |
Download gRPC golang library code
1 | cd $GOPATH |
Hello World Example
We are gonna work through official’s example which reside in google.golang.org/grpc/examples/helloworld:
1 | ├── greeter_client |
- greeter_client is a rpc client says hello to remote server
- greeter_server is a rpc server receive client’s simple hello request then give response: just a request/reply way of communicating
- in helloworld directory
- helloworld.proto: rpc protocol definition file, using the proto definition syntanx
- helloworld.pb.go: rpc library used by both RPC server and client
let’s run RPC server first:
1 | go run greeter_server/main.go |
then run client which simply say hello to the server:
1 | go run greeter_client/main.go frank |
we got:
1 | 2018/10/03 17:39:36 Greeting: Hello frank |
We just succeeded in running our first gRPC app!
Some Illustration
in helloworld.proto
1 | ... |
we can see that only difference with pure protobuf definition is we define a service, which use rpc keyword to indicate methods of a given service, actually, we can see gRPC as communicating with remote service which provide a couple of methods to invoke.
on the client side, what we just need to do is dial and invoke client.SayHello, on server side, we need to implement the Server interface according to what we need:
1 | type server struct{} |
and then register it the service:
1 | s := grpc.NewServer() |
In RPC world, when you want to provide a service on the server, you need to register it on server, so clients can find out it by server address and service name
Make your change
The helloworld example works directly because the source we got already has gRpc server/client code generated, let’s try change it a little bit, add another method for Greeter service:
1 | rpc SayHelloAgain(HelloRequest) returns (HelloReply) {} |
Basicly, it is quite similiar with SayHello, same input and output. We need to regenerate gRpc code:
1 | cd src/google.golang.org/grpc/examples/ |
plugins=grpc means use grpc plugin to generate grpc code while processing proto file.
in greeter_server/main.go, add implementation for SayHelloAgain method:
1 | func (s *server) SayHelloAgain(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) { |
in greeter_client/main.go, invoke SayHelloAgain:
1 | rAg, errAg := c.SayHelloAgain(ctx, &pb.HelloRequest{Name: name}) |
run the server, run client with go run greeter_client/main.go frank, you’ll see the SayHelloAgain method is correctly invoked:
1 | 2018/10/03 17:39:36 Greeting: Hello frank |
the original example could be found here
Conclusion
In this blog we explained what is RPC/gRPC, the reason why we need it:
- Easy to use, programmer do not need to go through a lot of network, data encode/decode details
- Efficient, because it transfers binary data
- Easy to extend, because it is built on HTTP/2
And we use official’s example to show how gRPC works.
Reference
Remote procedure call
Why gRPC uses Protobuf and HTTP/2 together?
Go Quick Start
What is gRPC?
gRPC Basics - Go