gRPC для JavaScript (Node.js): библиотеки и примеры кода

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

gRPC для JavaScript (Node.js): библиотеки и примеры

gRPC — это высокопроизводительный фреймворк для удалённого вызова процедур (RPC), разработанный Google. Он использует Protocol Buffers (protobuf) для сериализации данных и HTTP/2 для транспорта. В экосистеме Node.js gRPC позволяет создавать быстрые и надёжные микросервисы с поддержкой двунаправленной потоковой передачи. В этой статье мы разберём основные библиотеки, установку и напишем рабочий пример сервера и клиента.

Основные библиотеки для gRPC в Node.js

Для работы с gRPC в среде Node.js существует несколько ключевых пакетов:

  • @grpc/grpc-js — чистая реализация gRPC на JavaScript. Не требует нативных зависимостей (C++), что упрощает установку. Рекомендуется для большинства современных проектов.
  • @grpc/proto-loader — загрузчик файлов .proto. Преобразует protobuf-определения в объекты JavaScript для использования с @grpc/grpc-js.
  • protobufjs — альтернативная библиотека для работы с protobuf. Поддерживает как статическую, так и динамическую генерацию кода.
  • grpc-tools — CLI-инструменты для генерации JavaScript-кода из .proto файлов (альтернатива динамической загрузке).

В этом руководстве мы будем использовать связку @grpc/grpc-js и @grpc/proto-loader — это современный и стабильный подход.

Установка зависимостей

Создайте новый проект и установите необходимые пакеты:

mkdir grpc-node-example
cd grpc-node-example
npm init -y
npm install @grpc/grpc-js @grpc/proto-loader

Определение сервиса через .proto файл

Создайте файл hello.proto с описанием сервиса и сообщений:

syntax = "proto3";

service Greeter {
  rpc SayHello (HelloRequest) returns (HelloReply) {}
  rpc SayHelloStream (HelloRequest) returns (stream HelloReply) {}
}

message HelloRequest {
  string name = 1;
}

message HelloReply {
  string message = 1;
}

Здесь мы определили два метода: простой унарный SayHello и серверный стриминг SayHelloStream.

Реализация gRPC сервера на Node.js

Создайте файл server.js:

const grpc = require('@grpc/grpc-js');
const protoLoader = require('@grpc/proto-loader');

const PROTO_PATH = './hello.proto';

// Загружаем определение прото-файла
const packageDefinition = protoLoader.loadSync(PROTO_PATH, {
  keepCase: true,
  longs: String,
  enums: String,
  defaults: true,
  oneofs: true
});

const helloProto = grpc.loadPackageDefinition(packageDefinition).helloworld;

// Реализация методов сервиса
function sayHello(call, callback) {
  const name = call.request.name;
  console.log(`Received request: ${name}`);
  callback(null, { message: `Hello, ${name}!` });
}

function sayHelloStream(call) {
  const name = call.request.name;
  console.log(`Streaming for: ${name}`);

  // Отправляем несколько ответов
  for (let i = 0; i < 5; i++) {
    call.write({ message: `Hello ${name} - message ${i + 1}` });
  }
  call.end();
}

// Запуск сервера
function main() {
  const server = new grpc.Server();
  server.addService(helloProto.Greeter.service, {
    sayHello: sayHello,
    sayHelloStream: sayHelloStream
  });

  server.bindAsync('0.0.0.0:50051', grpc.ServerCredentials.createInsecure(), () => {
    console.log('gRPC server running on port 50051');
    server.start();
  });
}

main();

Реализация gRPC клиента на Node.js

Создайте файл client.js:

const grpc = require('@grpc/grpc-js');
const protoLoader = require('@grpc/proto-loader');

const PROTO_PATH = './hello.proto';

const packageDefinition = protoLoader.loadSync(PROTO_PATH, {
  keepCase: true,
  longs: String,
  enums: String,
  defaults: true,
  oneofs: true
});

const helloProto = grpc.loadPackageDefinition(packageDefinition).helloworld;

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

  // Унарный вызов
  client.sayHello({ name: 'PythonLib' }, (error, response) => {
    if (error) {
      console.error('Error:', error);
      return;
    }
    console.log('Unary response:', response.message);
  });

  //                    

Рекомендаций