Este guia demonstra a configuração de um servidor gRPC utilizando NestJS e TypeScript.
Estrutura do Projeto
A estrutura principal envolve os seguintes arquivos:
- Implemetnação do servidor
- Arquivo de definição proto
- Classe de inicialização (main.ts)
- Configuração do módulo (app.module.ts)
Dependências
As dependências necessárias para gRPC e microservices com NestJS incluem:
{
"@grpc/proto-loader": "^0.6.1",
"@nestjs/common": "^7.6.15",
"@nestjs/config": "^0.6.3",
"@nestjs/core": "^7.6.15",
"@nestjs/microservices": "^7.6.15",
"@nestjs/mongoose": "^7.2.4",
"@nestjs/platform-express": "^7.6.15",
"reflect-metadata": "^0.1.13",
"rimraf": "^3.0.2",
"rxjs": "^6.6.6",
"winston": "^3.3.3",
"winston-daily-rotate-file": "^4.5.1",
"@nestjs/schedule": "^0.4.3",
"cron": "^1.8.2",
"fastq": "^1.11.0",
"grpc": "^1.24.6",
"nest-winston": "^1.4.0",
"schedule": "^0.5.0"
}
Classe de Inicialização (main.ts)
A classe main.ts é responsável por inicializar a aplicação NestJS e cofnigurar o microserviço gRPC.
Observação: Ao configurar a URL, utilize o IP em vez de localhost para evitar problemas de conexão.
Neste exemplo, o servidor HTTP estará na porta 4001 e o servidor gRPC na porta 4000.
import { join } from 'path';
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { MicroserviceOptions, Transport } from '@nestjs/microservices';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
// Configuração do microserviço gRPC
app.connectMicroservice<microserviceoptions>({
transport: Transport.GRPC,
options: {
package: 'market_data_collector', // Nome do pacote definido no proto
url: '192.168.0.140:4000', // Endereço do servidor gRPC
protoPath: join(__dirname, 'proto/MarketData.proto'), // Caminho para o arquivo proto
},
});
await app.startAllMicroservicesAsync();
await app.listen(4001); // Porta para o servidor HTTP
}
bootstrap();
</microserviceoptions>
Configuração do Módulo Principal (app.module.ts)
O app.module.ts registra os módulos necessários e os controllers gRPC.
import { Module } from '@nestjs/common';
import { MongooseModule } from '@nestjs/mongoose';
import { MarketDataGrpcController } from './market-data-grpc.controller'; // Importe seu controller
@Module({
imports: [
// Exemplo de conexão com MongoDB:
// MongooseModule.forRoot('mongodb://root:root@192.168.0.159:27017/quantitative_trading?authSource=admin'),
MongooseModule.forRoot('mongodb://root:root@192.168.0.159:27017/quantitative_trading?authSource=admin'),
MongooseModule.forFeature([]), // Registre seus schemas aqui se necessário
],
controllers: [MarketDataGrpcController], // Registre o controller gRPC
providers: [],
})
export class AppModule {}
Arquivo Proto (.proto)
O arquivo MarketData.proto define os serviços e mensagens gRPC.
syntax = "proto3";
option java_multiple_files = true;
option java_package = "com.company.market_data_collector";
option java_outer_classname = "MarketData";
option objc_class_prefix = "company";
package market_data_collector;
// Define o serviço para coleta de dados de mercado
service MarketDataService {
// Rota para receber dados de mercado
rpc PushMarketData(PushMarketDataReq) returns( MarketDataRet);
}
// Mensagem de requisição para enviar dados de mercado
message PushMarketDataReq {
string data = 1; // Campo de dados em formato string
}
// Mensagem de resposta para dados de mercado
message MarketDataRet {
string data = 1; // Campo de dados em formato string
}
Controller gRPC (MarketDataGrpcController)
MarketDataGrpcController implementa a lógica do serviço gRPC.
import { Controller } from '@nestjs/common';
import { GrpcMethod } from '@nestjs/microservices';
// Interfaces para tipagem das mensagens gRPC
interface PushMarketDataReq {
data: string;
}
interface PushMarketDataRet {
data: string;
}
@Controller()
export class MarketDataGrpcController {
constructor() {}
// @GrpcMethod define o nome do serviço e do método gRPC
@GrpcMethod('MarketDataService', 'PushMarketData')
pushMarketData(request: PushMarketDataReq): PushMarketDataRet {
console.log('Requisição recebida:');
console.log(request);
// Lógica para processar os dados recebidos
// Retorna uma resposta simples
return { data: 'Dados recebidos com sucesso!' };
}
}
Observação sobre o arquivo proto: Ao iniciar a aplicação, pode ocorrer um erro indicando que o arquivo proto não foi encontrado. Nesse caso, copie manualmente o arquivo proto para o diretório de saída compilado (geralmente na pasta dist).