September 25, 2019 - by Colin J. Ihrig
The APIs and Web services of today rely heavily on technologies such as GraphQL, REST, JSON, and the ubiquitous HTTP. In recent years, gRPC has emerged as an option for building high performance services using the remote procedure call (RPC) paradigm.
This post introduces the basics of gRPC, with an emphasis on its use with Node.js. We’ll briefly explore the underlying technologies used by gRPC before diving into some of the features gRPC provides. Finally, the post will conclude by discussing some of the architectural impacts that should be considered before adopting gRPC for your next project.
Officially, gRPC is a recursive acronym standing for gRPC Remote Procedure Calls. Unofficially, the “g” very clearly stands for Google, the company that originally created the framework. Google went on to put gRPC into the Cloud Native Computing Foundation, but still controls the project. Beyond Google, gRPC boasts a number of large users including Netflix, Dropbox, Docker, and many more.
gRPC markets itself as “a modern open source high performance RPC framework.” The “high performance” claims stem from the framework’s underlying technology choices. Unlike most web frameworks, gRPC is built on HTTP/2, not HTTP/1.1, which typically provides a performance boost on its own. gRPC also leverages protocol buffers, which serialize requests and responses in a more compact binary format. While protocol buffer serialization/deserialization incurs some processing overhead, it reduces the number of bytes sent over the network, which is often the slowest part of a web-based application.
In addition to its use of HTTP/2 and protocol buffers, gRPC supports many features, including, but not limited to, the following:
gRPC is supported across an array of languages, including C++, Java, Python, Ruby, Go, and Node.js. Many of these implementations, including the Node.js one, are built on top of a shared core library written in C. For Node.js developers, this means adding a dependency on the grpc
compiled addon when building gRPC clients and servers. While certainly manageable, compiled modules do generally add a layer of complexity to projects. The gRPC team attempts to mitigate some of the hassle by providing “~130 builds of their native module for different environments.” Even with prebuilt binaries available, compilation/build issues are routinely opened on the project’s issue tracker.
In August of 2017, Node.js 8.4.0 added experimental support for HTTP/2 in core. This feature allowed the gRPC team to begin experimenting with a TypeScript implementation, culminating with the alpha release of @grpc/grpc-js
in April of 2018. Unlike the compiled addon, the TypeScript implementation does not support loading protocol buffers. That functionality has moved to the @grpc/proto-loader
module. Beyond that notable difference, @grpc/grpc-js
aims to be a drop-in replacement for the grpc
module.
Node.js 10.10.0 moved the http2
module out of experimental status. To celebrate (and avoid depending on the compiled addon), I wrote grpc-server-js
, a pure JavaScript gRPC server implementation. At the time, @grpc/grpc-js
did not yet support creating server applications. I’m happy to report that as of June 2019, grpc-server-js
has been ported to TypeScript and upstreamed to @grpc/grpc-js
. The server component is available in releases of @grpc/grpc-js
starting with version 0.5.0.
The choice to adopt gRPC may impact other architectural decisions in a larger system. This is due to gRPC’s use of HTTP/2 and its own higher level protocol, which the rest of the system needs to understand and interact with. For example, off-the-shelf load balancers and other components have varying levels of support for gRPC. Performance comparisons between gRPC and non-gRPC code can also become more difficult if the same benchmarking tools cannot be used.
The biggest hurdle to gRPC adoption for many applications is its lack of support in browsers. Although many browsers now support HTTP/2, some do not. Furthermore, even browsers that support HTTP/2 do not directly expose the requisite APIs to control HTTP/2 framing, which is required by gRPC. To work around these shortcomings, gRPC-Web was developed as a browser solution. Unfortunately, gRPC-Web only supports a subset of the features supported by gRPC over HTTP/2. gRPC-Web also currently requires adding an Envoy proxy server to your system, which translates between gRPC-Web and normal gRPC traffic.
This blog post has introduced several gRPC concepts at a high level, but has only scratched the surface. If you’re interested in learning more, please do not hesitate to reach out. Or, if you can make it to Verona, Italy on October 3, 2019, come to Node.js Day Italy and check out my talk, Getting Started with gRPC and Node.js.