Computer scienceBackendNode.jsClient-server interaction

gRPC

10 minutes read

Imagine you have two computers that need to talk to each other to complete tasks—gRPC is the language they use to communicate efficiently. gRPC is a high-performance, open-source universal RPC (Remote Procedure Call) framework initially developed by Google. In the realm of Node.js, gRPC facilitates the creation of efficient and scalable server-client communications. It's a system designed to connect services efficiently, allowing for fast and reliable communication over a network.

Understanding gRPC

gRPC is an open-source framework that allows you to define functions on a server that can be called from a client located elsewhere on the network. gRPC is based on the idea of defining a service, specifying the methods that can be called remotely with their parameters and return types. On the server side, the server implements this interface and runs a gRPC server to handle client calls. On the client side, the client has a stub (referred to as just a client in some languages) that provides the same methods as the server.

It uses Protocol Buffers (protobuf) to define the service methods and messages in a .proto file. These definitions are then transformed into client and server code that can communicate across various programming languages. Protocol Buffers are a language-neutral and platform-neutral mechanism for serializing structured data.

gRPC illustration

Benefits of using gRPC

  • Quick and efficient: gRPC uses modern technology (HTTP/2) to quickly communicate between computers.

  • Data Efficiency: Protocol Buffers, gRPC's data serialization method, is more compact than JSON.

  • Performance: Utilizing HTTP/2, gRPC streams allow for multiplexed requests, leading to lower latency and higher throughput.

  • Language Interoperability: Service definitions can be written once and implemented across different languages.

  • Communication Protocol: Protocol Buffers offer a lightweight and efficient communication protocol.

You might use gRPC in Node.js when you’re:

  • Building a network of services that need to talk to each other (microservices).

  • Creating APIs that need to be fast and handle lots of data.

  • Working in a team where different parts of an application are written in different languages.

gRPC vs. REST

While gRPC is designed for low-latency and high-throughput communication, REST is a more traditional web service communication protocol that uses HTTP/1.1. REST is widely used for its simplicity and the convenience of using JSON for data interchange. However, gRPC provides advantages in terms of performance and efficiency, especially in microservices architectures where internal service-to-service communication is critical.

Setting up a gRPC project

Before diving into gRPC, ensure you have Node.js and npm installed on your system. Create a new folder for your project and start a new Node.js project inside it by running npm init.

Defining a gRPC service with Protocol Buffers (protobuf)

Protocol Buffers, often shortened to protobuf, are a way of defining the shape of your data so that it can be easily read and written across different programming languages, i.e. it defines the schema for services, messages, and data types.

Create a file named helloworld.proto. This file will contain the definition of the service and the messages (payload) using Protocol Buffers syntax.

syntax = "proto3";

package helloworld;

// The greeting service definition.
service Greeter {
  // Sends a greeting
  rpc SayHello (HelloRequest) returns (HelloReply) {}
}

// The request message containing the user's name.
message HelloRequest {
  string name = 1;
}

// The response message containing the greetings.
message HelloReply {
  string message = 1;
}

In the code snippet:

  • syntax = "proto3"; specifies that we are using Protocol Buffers version 3.

  • package helloworld; defines a package to prevent name clashes between different projects.

  • Inside the service Greeter, we define an RPC method SayHello that takes a HelloRequest message and returns a HelloReply message.

  • HelloRequest and HelloReply are message types with one field each.

The message types specify the structure of the data that will be serialized and sent over the network. Each field within the message types is assigned a unique identifier (e.g., 1), which is used in the binary encoding to identify the fields.

Implementing a gRPC Server

Create a file named server.js. This file will contain the server implementation.

const grpc = require('@grpc/grpc-js');
const protoLoader = require('@grpc/proto-loader');
const packageDefinition = protoLoader.loadSync('helloworld.proto', {});
const hello_proto = grpc.loadPackageDefinition(packageDefinition).helloworld;

// Implement the SayHello RPC method.
function sayHello(call, callback) {
  callback(null, { message: 'Hello, ' + call.request.name });
}

// Start a gRPC server and listen on port 50051.
function main() {
  const server = new grpc.Server();
  server.addService(hello_proto.Greeter.service, { sayHello: sayHello });
  server.bindAsync('0.0.0.0:50051', grpc.ServerCredentials.createInsecure(), () => {
    console.log('gRPC server running on port 50051');
  });
}

main();

This code snippet sets up a basic gRPC server in Node.js that can respond to specific requests from clients. First:

  • You load the protobuf definition using the proto-loader package and create a gRPC service from it.

  • The sayHello function is the implementation of the SayHello RPC method, which takes a request and sends back a greeting.

  • The server is set up to listen on port 50051 and has no transport security (insecure) for simplicity.

Finally, the server is started, ready to handle requests and send responses as defined by the sayHello function. Your server's sayHello function receives the request and sends back a greeting.

proto-loader is a Node.js package that is part of the gRPC ecosystem. It is used to load .proto files, which contain the Protocol Buffers service definitions, and dynamically generate the corresponding JavaScript objects.

Implementing a gRPC client

Create a file named client.js. This file will contain the client implementation.

const grpc = require('@grpc/grpc-js');
const protoLoader = require('@grpc/proto-loader');
const packageDefinition = protoLoader.loadSync('helloworld.proto', {});
const hello_proto = grpc.loadPackageDefinition(packageDefinition).helloworld;

function main() {
  const client = new hello_proto.Greeter('localhost:50051', grpc.credentials.createInsecure());

  // Request object
  const request = { name: 'World' };

  // Call the SayHello RPC method
  client.sayHello(request, function(err, response) {
    if (err) {
      console.error('Error:', err);
    } else {
      console.log('Greeting:', response.message);
    }
  });
}

main();

In the client.js file

  • The client is set up to connect to the server at localhost:50051.

  • We create a request object with the name 'World'.

  • To make a request to the gRPC server, the client sends a SayHello request to the server and waits for a response.

  • When the server replies, the client checks for errors and, if everything is fine, it logs out the greeting it received.

Testing the server and client

Install the necessary gRPC Node.js packages by running:

npm install @grpc/grpc-js @grpc/proto-loader

Start the server by running:

node server.js

In a different terminal, run the client:

node client.js

You should see the server printing that it's running on port 50051

gRPC server

and the client printing the greeting message: "Greeting: Hello, World".

Running instance of client sending request

Conclusion

Understanding and implementing gRPC in Node.js applications can significantly enhance communication efficiency within your services. It’s fast, versatile, and can work across different programming languages, making it a great choice for modern web services. Following the steps outlined in this topic, you can create efficient, and reliable communication between your services, helping you build better and more scalable applications.

7 learners liked this piece of theory. 0 didn't like it. What about you?
Report a typo