Skip to content

gRPC 是一个高性能、开源的远程过程调用(RPC)框架,它基于 HTTP/2 协议传输,使用 Protocol Buffers(Protobuf) 作为默认的序列化方式,支持多种语言。

应用场景

  • 微服务间通信
  • 分布式系统中的高效数据交换
  • 需要高性能和低延迟的场景
  • 移动端与后端通信

序列化方式

默认使用 Protocol Buffeters:

proto
syntax = "proto3"; // 协议版本

package demo; // 包名

service DemoService { // 服务定义:远程调用方法(rpc)
  rpc SayHello (HelloRequest) returns (HelloReply);
}

message HelloRequest { // 消息定义
  string name = 1;
}

message HelloReply {
  string message = 1;

也支持其他格式如 JSON、XML 等(非默认)。

服务端

在 Nest 中,使用 @GrpcMethod() 装饰器实现 .proto 中声明的方法,对应 .proto 文件中声明的一组 service 中的某个 rpc 方法:

js
@GrpcMethod('DemoService', 'SayHello')
sayHello(data: HelloRequest): HelloResponse {
  console.log({ message: `Hello ${data.name}!` });
  return { message: `Hello ${data.name}!` };
}

解析以 json 传入的 data 数据并且返回一个重新构造的 json

HTTP 客户端

客户端正常通过 HTTP 方式启动:

ts
// main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  await app.listen(3000); // 启动 HTTP 服务,监听 3000 端口
}
bootstrap();

创建 gPRC 客户端,注册到 Nest 的依赖注入容器中:

ts
@Module({
    imports: [
        ClientsModule.register([
            {
                name: 'DEMO_SERVICE',
                transport: Transport.GRPC,
                options: {
                    package: 'demo',
                    protoPath: 'src/proto/demo.proto',
                    url: 'localhost:5000'
                }
            }
        ])
    ],
    controllers: [CalController],
    providers: [CalService]
})

注入到 call.service.ts 中使用:

ts
import { Inject, Injectable, OnModuleInit } from '@nestjs/common';
import { ClientGrpc } from '@nestjs/microservices';
import { Observable } from 'rxjs';

interface GrpcCalService {
  sayHello(data: { name: string }): Observable<{ message: string }>;
}

@Injectable()
export class CalService implements OnModuleInit {
  private grpcService: GrpcCalService;

  constructor(@Inject('DEMO_SERVICE') private readonly client: ClientGrpc) {} // 注入客户端

  onModuleInit() {
    this.grpcService = this.client.getService<GrpcCalService>('DemoService'); // 获取远程服务的引用
  }

  sayHello(name: string) {
    return this.grpcService.sayHello({ name });
  }
}

注意到这里的 sayHello 是一个流对象,因为 gRPC 支持流式传输,无论是否流式,Nest 统一用 Observable 处理。

英文模式名称中文模式名称通信模式描述
Unary RPC一元 RPC客户端发送单个请求,服务端返回单个响应
Server Streaming服务端流客户端发送单个请求,服务端通过流返回多个响应
Client Streaming客户端流客户端通过流发送多个请求,服务端返回单个响应
Bidirectional Streaming双向流客户端和服务端通过独立流双向通信,可任意顺序读写消息