gRPC для JavaScript (Node.js): библиотеки и примеры
gRPC — это высокопроизводительный фреймворк для удалённого вызова процедур (RPC), разработанный Google. Он использует Protocol Buffers (protobuf) для сериализации данных и HTTP/2 для транспорта. В экосистеме Node.js gRPC позволяет создавать надёжные микросервисы с строгой типизацией, поддержкой стриминга и двусторонней связи. В этой статье мы рассмотрим основные библиотеки для работы с gRPC в JavaScript (Node.js) и разберём практический пример сервера и клиента.
Основные библиотеки для gRPC в Node.js
Для работы с gRPC в Node.js используется два основных пакета:
- @grpc/grpc-js — чистая JavaScript-реализация gRPC. Не требует нативных зависимостей, работает на всех платформах, поддерживает все функции gRPC (унарные вызовы, серверный и клиентский стриминг, двусторонний стриминг).
- @grpc/proto-loader — утилита для загрузки
.protoфайлов во время выполнения. Позволяет динамически создавать JavaScript-объекты из определений Protobuf.
Для компиляции .proto файлов в статические модули можно использовать grpc-tools (часть grpc-tools), но в современных проектах чаще применяют динамическую загрузку через @grpc/proto-loader.
Установка зависимостей
npm install @grpc/grpc-js @grpc/proto-loader
Пример: определение Proto-файла
Создадим файл helloworld.proto с простым сервисом:
syntax = "proto3";
package helloworld;
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
message HelloRequest {
string name = 1;
}
message HelloReply {
string message = 1;
}
Серверная часть (Node.js)
Создадим файл server.js:
const grpc = require('@grpc/grpc-js');
const protoLoader = require('@grpc/proto-loader');
const path = require('path');
const PROTO_PATH = path.join(__dirname, 'helloworld.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 || 'Guest';
callback(null, { message: `Привет, ${name}!` });
}
function main() {
const server = new grpc.Server();
server.addService(helloProto.Greeter.service, { sayHello: sayHello });
server.bindAsync('0.0.0.0:50051', grpc.ServerCredentials.createInsecure(), () => {
console.log('gRPC сервер запущен на порту 50051');
server.start();
});
}
main();
Клиентская часть (Node.js)
Создадим файл client.js:
const grpc = require('@grpc/grpc-js');
const protoLoader = require('@grpc/proto-loader');
const path = require('path');
const PROTO_PATH = path.join(__dirname, 'helloworld.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());
const userName = process.argv[2] || 'Мир';
client.sayHello({ name: userName }, (error, response) => {
if (error) {
console.error('Ошибка:', error.message);
return;
}
console.log('Ответ сервера:', response.message);
});
}
main();
Запуск и тестирование
Запустите сервер в одном терминале:
node server.js
В другом терминале выполните клиент:
node client.js Иван
Вы должны увидеть:
Ответ сервера: Привет, Иван!
Продвинутые возможности gRPC
gRPC поддерживает несколько типов RPC-вызовов:
- Унарный (Unary) — один запрос, один ответ (пример выше).
- Серверный стриминг — один запрос, поток ответов.
- Клиентский стриминг — поток запросов, один ответ.
- Двуст