gRPC API

All about GRPC


Before learning gRPC, we need to understand what is RPC (Remote Procedure Call) and how it differs from Local Procedure Call.

LinkIconWhat is RPC

RPC (Remote Procedure Call) is a function call that runs in another process, usually in another machine.

A function like:

user = getUserById(42)

LinkIcongRPC

gRPC is a high-performance RPC framework created at Google and open sourced in 2015.

gRPC doesn't use JSON, it uses Protocol Buffers (called Protobuf).

Why not JSON? JSON is readable but machine doesn't need readable text. They need fast and compact data like Protobuf.

Protobuf is a binary format which means much smaller sizes, much faster serialization, strong typing.

You can define your data structures and services methods in a .proto file and gRPC generates the code automatically for different languages.

JSON vs Protobuf

// JSON
{
  "id": 0,
  "name": "",
  "active": false
}
// Protobuf
message User = {
  int32 id = 1;
  string name = 2;
  bool active = 3;
}

The way Protobuf works is it simply:

  • take a data object
  • convert it into a tiny binary format
  • send it over the network
  • server rebuilds the same data object and sends response back using the same Protobuf process.

This ensures both client and server speaks the exact same data structure.

Because all of this is generated from .proto files, you don't actually write any networking code. gRPC handles serialization, routing, and communication. Using gRPC feels just like calling a normal function that your backend understands.

Benefits of using gRPC:

  • gRPC runs on top of HTTP/2 instead of HTTP/1.1

    HTTP/1.1 requests needs its own TCP connection and they often get stuck waiting each other causing delay and bottlenecks.

    But HTTP/2 fixes all of this. It allows serveral requests travel over a single TCP connection reducing latency and blocking.

    This feature makes gRPC perfect for high-speed real-time communication.

  • Speed

    Protobuf messages are tiny compared to JSON.

  • Less CPU Usage

    Since gRPC uses binary format, then binary serialization to send over the network is much cheaper than JSON.

  • Low Latency

    With gRPC, you get low latency since HTTP/2 requests don't block each other like in HTTP/1.1.

  • Less Bandiwth

    Payloads in gRPC are far smaller than JSON.

When not to use gRPC:

  • Public APIs
  • Browser doesn't support gRPC natively, must install extra packages

When to use gRPC:

  • Communicating between internal services written in different languages (microservices)

LinkIconBuilding gRPC APIs

Install dependencies.

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

Define a proto file.

BashIcon
syntax = "proto3";
 
package user;
 
service UserService {
  rpc GetUser (GetUserRequest) returns (User);
}
 
message GetUserRequest {
  int32 id = 1;
}
 
message User {
  int32 id = 1;
  string email = 2;
  string name = 3;
}

Create RPC server.

import grpc from '@grpc/grpc-js';
import protoLoader from '@grpc/proto-loader';
 
const packageDef = protoLoader.loadSync('user.proto');
const proto = grpc.loadPackageDefinition(packageDef).user;
 
function getUser(call, callback) {
  const user = {
    id: call.request.id,
    email: 'jose@example.com',
    name: 'Jose',
  };
 
  callback(null, user);
}
 
const server = new grpc.Server();
server.addService(proto.UserService.service, { getUser });
 
 
server.bindAsync(
  '0.0.0.0:50051',
  grpc.ServerCredentials.createInsecure(),
  () => server.start()
);

Create the gRPC client.

import grpc from '@grpc/grpc-js';
import protoLoader from '@grpc/proto-loader';
 
const packageDef = protoLoader.loadSync('user.proto');
const proto = grpc.loadPackageDefinition(packageDef).user;
 
const client = new proto.UserService(
  'localhost:50051',
  grpc.credentials.createInsecure()
);
 
client.getUser({ id: 42 }, (err, response) => {
  console.log(response);
});