Implementing gRPCweb with Istio Envoy
June 10, 2019
This is a post which was about how web applications can benefit from gRPC by leveraging a gRPC sub-project called gRPC-Web along with Istio.
gRPC-Web addresses a shortcoming in the core gRPC framework: the fact that it doesn’t work so well with web applications running on browsers. That’s because even though most browsers support HTTP/2 and gRPC is based on HTTP/2, gRPC has its own protocols that web applications must understand in order to work properly with it. But web applications do not have this capability because browsers don’t support gRPC out of the box. Developers are increasingly looking to benefit from the advantages the core gRPC framework confers beyond backend microservices, thus gRPC-Web was born.
One way to get around the above problem is to use the gRPC-Web plugin and run a proxy like Envoy along with it. Envoy serves as the default proxy for Istio, and by configuring its gRPC-Web filter, we can create seamless, well-connected, cloud native web applications. Traditionally, services have exposed their functionality over REST APIs. This gives you service isolation, scalability, velocity and independence. But the REST API itself is not type safe; it doesn’t give you forward and backward compatibility and performance can be constrained.
Protobufs let us define the same API in a standard way with an interface definition language (IDL), which resolves the issues that REST APIs aren’t addressing. Replace the REST API in services with gRPC and the backend works pretty much the same as before. That doesn’t totally solve the problem though (i.e. the web UI still cannot talk to backend services because browsers don’t directly support gRPC). You get around that by using the gRPC-Web library and a proxy. With those in place, web applications can now talk to a gRPC backend directly.
Another alternative is to use an HTTP server pattern, where you implement some kind of an intermediate middleware that takes simple HTTP requests from the browser and converts them to gRPC. But that won’t scale because you need to keep updating the API, and it’s not maintainable when you have a lot of microservices and need to create these kinds of APIs for every single microservice. Use a proxy-based approach built around a service mesh framework and it will transcode your HTTP requests into gRPC requests so you can get rid of the HTTP server.
In my talk, I showed a demo of a web app that uses gRPC-Web on the front end and a simple Go backend exposing a gRPC API. I didn’t configure a proxy directly but instead deployed the application on Istio, which configured the proxy and the gRPC-Web filter automatically. Crucially, the front and backend are now talking seamlessly, and you also gain a whole set of features from Istio as well.
One of the most important of these is observability. You can now observe your microservices on the Grafana dashboard that shows key metrics like client and server request volumes, success rates, request durations and response rates. Then, because you are working with Istio, you can also trace all HTTP and gRPC requests in a much more standard manner using Jaeger. Apart from these, Kiali lets you visualize your deployment as a service graph which it generates by observing the traffic flow in real-time.
The bottom line here is that by switching over to a gRPC-Web and Istio paradigm, developing a cloud native application becomes a relatively seamless experience.
You can find a demo on GitHub for this. Feel free to check out the code and deploy the demo on Istio to see how it performs.