Today, the main topic that we’ll be learning about is gRPC. We’ll also learn about microservices, the advantages of gRPC, and the difference between gRPC libraries. At the end of this article, I will run through a basic tutorial for getting gRPC working with Node.js. So let’s start!
gRPC is a very modern, open-source framework released in August 2016. It is a high-performance Remote Procedure Call framework (hence the name RPC) capable of running in any environment. What sets gRPC apart from similar frameworks is its ability to offer much higher performance when clients and server applications are trying to communicate with each other. So we have established that it gives us many performance gains, but we also need to consider that gRPC is much harder to implement. Many of us developers have never used it before, so we’ll need to take this into account.
We are all familiar with the traditional ways for clients and servers to connect, most notably using REST API, which we know as RESTful API. But there is also GraphQL, an open-source data query language for APIs. I’ll walk you through the difference between the two types. Now in the case of REST API, it typically works on the client whereas with GraphQL all of that logic is set up on the backend. Each system has its pros and cons, giving us different options to choose from. I’ll show you the differences between these frameworks in the upcoming sections. You’ll learn that they’re composed of various technical stacks combined to create what is known as a microservice.
Before we start, I’m sure you are all aware and know what microservices are, but I will tell you anyway. 🙂 So, let me give you an introduction to what microservices are. They are an architectural structure that is a collection of various services that form an overall style. This type of architecture allows a developer or team to build complex applications rapidly. In doing so, we could scale up a technology stack whenever we needed to, like in the case of developing a new feature request for an app we are working on.
For example, we could have a backend microservice that uses Python, Node.js, and Go. Each language serves a purpose, and they need to connect together. If we were to try using gRPC in a browser, it would not work without installing the right setup and configurations. However, the perfect use case is when it comes to using it in a backend microservice environment like in our example with Python, Node.js, and Go.
It’s time for us to learn some advantages of gRPC, which I will demonstrate for you here. One of the advantages of using gRPC is its flexibility. When we use separate libraries, it’s common to do a lot of the setup for the different connection layers. Every language has a different HTTP client library, so maintaining and updating them all across the board for every single microservice that we use can create a lot of overhead and frustration.
Now with gRPC, it natively supports all of the HTTP clients setups so we don’t have to manually do it across all of our services. Another huge advantage is the fact that gRPC can do code generation using protocol buffers. They are effectively like a blueprint for doing communications between different parties.
We already know that REST APIs are a traditional method for sending data. And unlike gRPC they do not use blueprints to speak. So you can send the messages as key-value pairs which are not checked until they reach our recipient.
Take a look at the below example for a traditional `.json` file.
{
"id": "77etf783fwerf23f",
"name": "Luke Skywalker",
"profession": "Jedi Knight",
"email": "[email protected]"
}
When we compare it to gRPC on the other hand we can see that it defines services in a `.proto` file like in the code snippet I have created below. These services are basically like a schema for the data that is going to be sent, much like defining a schema for the data in a GraphQL file. Similarly, using a tool like Swagger for our RESTful API design needs.
message Profile {
required int32 id = 1;
required string name = 2;
optional string email = 3;
}
So in this example, we are defining which procedures can be called from other microservices. That would be our Python, Node.js, and Go backends in this case. When we want to have the source code generated and output for the languages that we are working on we would use a compiler on the `.proto` file, and then it would output the correct source code for the languages which we specified.
Let me give you another one of the big areas where gRPC excels over REST and GraphQL. By now, we know that it is in speed and performance and the fact that it uses HTTP 2.0 is another reason because it is using the latest specification which is more modern when compared to HTTP 1.0. It has significantly more performance improvements due to the fact that protocol buffers become serialized and the data is sent using binary.
This will do wonders for us as it leads to much better security because gRPC supports SSL/TLS, ALTS, and Token-based authentication with Google. We can read about all of these concepts in the Authentication section of their official documentation. Streaming gives us another advantage because gRPC can do client, server, and bidirectional streaming which is available in HTTP 2.0 only.
When we use JSON data it tends to be uncompressed because we are dealing with key-value pairs whereas with a binary file the data is much smaller. The flexibility combined with speed gains makes gRPC a good choice for us when we are trying to build an architecture that needs a high level of performance.
What we need to realize is that the original Node.js gRPC library was released first although it is no longer recommended because was deprecated in favour of the newer grpc-js library. The more modern grpc-js library has been available since April 2020 and it is a pure TypeScript reimplementation of the previous library.
According to the creators, it supports the following features which should cover the majority of use cases:
While the newer library is almost a like-for-like replacement there are some differences that are better explained to us in the Migrating from grpc section on their npm package page.
We should familiarize ourselves with Nest.js which is an extremely popular Node.js backend framework that uses TypeScript. The documentation on their website is actually quite good and they even have a microservices section dedicated to using Nest gRPC, which we can learn from.
They also use the `.proto` file standard to dynamically link the clients and servers together so that we can put together remote procedure calls that will automatically serialize and deserialize the structured data.
Let’s create a simple example so we can see what a gRPC project would look like in Node.js. I have included the GitHub repo with the codebase here https://github.com/andrewbaisden/nodejs-grpc.
First, let’s navigate to a directory in our computer using the command line, and then let’s copy and paste the code below to scaffold a project.
mkdir nodejs-grpc
cd nodejs-grpc
npm init -y
npm i @grpc/grpc-js @grpc/proto-loader minimist nodemon
touch welcome_client.js welcome_server.js welcome.proto
Now, we need to open the project in a code editor or IDE and copy and paste the code below. We will put the code below in the files we just created.
First, let’s put this code in our `wlecome_client.js` file.
const PROTO_PATH = __dirname + '/welcome.proto';
const grpc = require('@grpc/grpc-js');
const protoLoader = require('@grpc/proto-loader');
const packageDefinition = protoLoader.loadSync(PROTO_PATH, {
keepCase: true,
longs: String,
enums: String,
defaults: true,
oneofs: true,
});
const welcome_proto = grpc.loadPackageDefinition(packageDefinition).welcome;
/**
* Implements the SayWelcome RPC method.
*/
function SayWelcome(call, callback) {
callback(null, { message: 'Welcome ' + call.request.name });
}
/**
* Starts an RPC server that receives requests for the Welcome service at the
* sample server port
*/
function main() {
const server = new grpc.Server();
server.addService(welcome_proto.Welcome.service, { SayWelcome: SayWelcome });
server.bindAsync(
'0.0.0.0:50051',
grpc.ServerCredentials.createInsecure(),
() => {
server.start();
}
);
}
main();
Now we will copy this code into our `welcome.proto` file.
syntax = "proto3";
package welcome;
// The welcome service definition.
service Welcome {
// Sends a welcome
rpc SayWelcome (WelcomeRequest) returns (WelcomeReply) {}
}
// The request message containing the user's name.
message WelcomeRequest {
string name = 1;
}
// The response message containing the welcome
message WelcomeReply {
string message = 1;
}
Now let’s go to the command line and run the commands below in different tabs/windows. We should make sure that we start the server before the client. When doing so we should see the message `Message: Welcome Luke Skywalker` outputted in the command line window for the client.
npm run start:server
npm run start:client
To learn more, take a look at the main documentation for gRPC. The framework officially supports many languages, platforms and OS versions. These include JavaScript, TypeScript, C#, Node.js, Go, Kotlin, PHP and many more which you can find in the documentation.
It is quite clear after reading this article that gRPC is awesome!
We covered a lot in this tutorial. We started by introducing gRPC and its various concepts. There is a lot more you can do with gRPC, read it in the docs gRPC to find out more, or if you have any questions, connect with us here at Sprkl.
Share
Enjoy your reading 9 Min Read
We promise you’ll only get notified
when new content is out
Font 1
Font 1
Font 1
Font 1
Font 1
Font 1
Font - code
Font - code