gRPC para JavaScript (Node.js): bibliotecas e exemplos
gRPC é um framework de alto desempenho para chamada remota de procedimentos (RPC), desenvolvido pelo Google. Ele utiliza Protocol Buffers (protobuf) para serialização de dados e HTTP/2 para transporte. No ecossistema Node.js, o gRPC permite criar microsserviços robustos com tipagem forte, suporte a streaming e comunicação bidirecional. Neste artigo, vamos explorar as principais bibliotecas para trabalhar com gRPC em JavaScript (Node.js) e analisar um exemplo prático de servidor e cliente.
Principais bibliotecas para gRPC em Node.js
Para trabalhar com gRPC em Node.js, são utilizados dois pacotes principais:
- @grpc/grpc-js — implementação pura em JavaScript do gRPC. Não requer dependências nativas, funciona em todas as plataformas e suporta todos os recursos do gRPC (chamadas únicas, streaming do servidor e do cliente, streaming bidirecional).
- @grpc/proto-loader — utilitário para carregar arquivos
.protoem tempo de execução. Permite criar dinamicamente objetos JavaScript a partir de definições Protobuf.
Para compilar arquivos .proto em módulos estáticos, pode-se usar grpc-tools (parte do grpc-tools), mas em projetos modernos é mais comum usar o carregamento dinâmico através do @grpc/proto-loader.
Instalação das dependências
npm install @grpc/grpc-js @grpc/proto-loaderExemplo: definição do arquivo Proto
Vamos criar o arquivo helloworld.proto com um serviço simples:
syntax = "proto3";
package helloworld;
service Greeter { rpc SayHello (HelloRequest) returns (HelloReply) {}}
message HelloRequest { string name = 1;}
message HelloReply { string message = 1;}Parte do servidor (Node.js)
Vamos criar o arquivo 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 || 'Convidado'; callback(null, { message: `Olá, ${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('Servidor gRPC iniciado na porta 50051'); server.start(); });}
main();Parte do cliente (Node.js)
Vamos criar o arquivo 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] || 'Mundo';
client.sayHello({ name: userName }, (error, response) => { if (error) { console.error('Erro:', error.message); return; } console.log('Resposta do servidor:', response.message); });}
main();Execução e teste
Inicie o servidor em um terminal:
node server.jsEm outro terminal, execute o cliente:
node client.js JoãoVocê deve