gRPC is cool. Then what?

grpc_square_reverse_4x

What is the most popular RPC right know? I would say restful with JSON. It is flexible, easy to test, using very common http stack and easy to do versioning. Then comes gRPC, offering more efficient network usage, faster serialization and deserialization and has good versioning support. I will not cover how to create basic service and the implementation, but will talk instead about using gRPC alongside existing restful API and doing versioning on gRPC.

In restful API there are routing and handler function which handle incoming request and responds it back. Another common practice is to have middleware to do pre or postprocessing on the request like logging and sanitizing. The question is could we use these existing functionality to work on our new gRPC service?
Everything is possible in engineering, but how big the changes is? It’s depending on your existing code.

Make it work together

This is common go webservice structure, or at least this is my favorite way to organize my code.

/middleware
 ./logging.go
/student
 ./handler.go
 ./data.go
/schedule
 ./handler.go
 ./data.go
/router.go
/main.go

Inside route.go is http routing in this app, may looks like this :

router := httprouter.New()
router.GET("/student/:id", student.GetIDHandler)
router.GET("/schedule/:id", schedule.GetIDHandler)

Then we will have two services on the gRPC which has their getID procedure.

service student {
 rpc getID(studentMessage) returns (idResponse){}
}

service schedule {
 rpc getID(scheduleMessage) returns (idResponse){}
}

On the go side we can do service multiplexing on the same connection for both services, let’s put it on gRPCServer.go .//creating gRPC server

s := gRPC.NewServer()
pb.RegisterStudentServer(s,studentServer{})
pb.RegisterScheduleServer(s,scheduleServer{})

studentServer and scheduleServer are struct which implement interface from the service definition. Here then we can encapsulate the real function which get the student or schedule ID then use it inside http handler and gRPC handler.

Middleware?

Middleware is a function which run before or after the real http handler being called, this is very popular on building http service. Could we do the same thing in gRPC? Yes. Can we reuse our existing code? In short, Yes. Long answer, not really.
Typically middleware function in golang would take `(w http.ResponseWriter, r *http.Request)` parameter, and ofcourse that would not work on gRPC. Again we need to encapsulate the real bussiness process then create the wrapper for gRPC.

So gRPC has some chaining mechanism like on http? Yes, gRPC has `StreamInterceptor` which allows us to have something like middleware. It’s not as easy as creating http middleware, but it’s quite straightforward don’t worry. https://github.com/gRPC-ecosystem/go-gRPC-middleware/blob/master/DOC.md

Mapping http / rest endpoint

We can’t map all restful interface and common functionality into gRPC since it has different nature and design. Http tends to use query string as parameter and for restful itself has object oriented nature. However gRPC is more in procedural side which there is a message and many functions to work with it.

For example we can do like this in http `/student/:id/family/address` or `/schedule/:id/alias_name` which also able to support multiple http method (GET,POST,PUT,DELETE,PATCH) and in addition it can take another query string parameters.

There are many possible approach for this use case, two extreemes to look at are creating one function which takes many parameter to identify what it needs and second is creating as many procedure as needed. For now I like the second extreeme, this is the example :

service student {
 rpc getFamilyAddressByID(studentMessage) returns (addressResponse){}
}

service schedule {
 rpc getAliasNameByID(scheduleMessage) returns (aliasNameResponse){}
}

Ofcourse there is limit for this approach, but at time the limit reached you should think back the design of your data structure.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s