gRPC 用于 TypeScript:库与示例
gRPC 是 Google 开发的高性能 RPC 框架,运行于 HTTP/2 之上,并使用 Protocol Buffers (protobuf) 进行数据序列化。在 TypeScript(以及 Node.js)中,gRPC 允许构建支持流式传输和双向通信的高效微服务架构。在本页面中,我们将介绍核心库、开发环境配置,并编写一个可运行的客户端-服务器应用程序示例。
TypeScript 中 gRPC 的核心库
在 TypeScript 生态系统中使用 gRPC,有三个关键包:
@grpc/grpc-js— 纯 JavaScript 实现的 gRPC(无原生依赖),完全支持 HTTP/2,适用于 Node.js 12+。@grpc/proto-loader—.proto文件加载器,基于 protobuf 定义动态创建 JavaScript 类。ts-proto— 从 proto 文件生成 TypeScript 类型的生成器。它是内置grpc-tools的替代方案,但对严格类型化有更好的支持。
使用一条命令安装所有组件:
npm install @grpc/grpc-js @grpc/proto-loader ts-protonpm install -D typescript @types/node创建 .proto 文件
从定义服务开始。创建文件 hello.proto:
syntax = "proto3";
package hello;
service Greeter { rpc SayHello (HelloRequest) returns (HelloReply); rpc SayHelloStream (HelloRequest) returns (stream HelloReply);}
message HelloRequest { string name = 1;}
message HelloReply { string message = 1;}使用 ts-proto 生成 TypeScript 类型
ts-proto 会生成完整的接口和消息类。安装 protoc 和插件:
npm install -g protoc-gen-ts-protoprotoc --ts_proto_out=./generated hello.proto结果将生成文件 generated/hello.ts,其中包含接口 HelloRequest、HelloReply 以及类型化的服务 GreeterClient。
服务器端(基于 TypeScript 的 gRPC 服务器)
创建文件 server.ts:
import * as grpc from '@grpc/grpc-js';import * as protoLoader from '@grpc/proto-loader';import { ProtoGrpcType } from './generated/hello';
const packageDef = protoLoader.loadSync('hello.proto');const grpcObj = (grpc.loadPackageDefinition(packageDef) as unknown) as ProtoGrpcType;const server = new grpc.Server();
server.addService(grpcObj.hello.Greeter.service, { SayHello: (call: any, callback: any) => { const name = call.request.name; callback(null, { message: `你好,${name}!` }); }, SayHelloStream: (call: any) => { const name = call.request.name; for (let i = 0; i < 5; i++) { call.write({ message: `消息 ${i + 1} 给 ${name}` }); } call.end(); }});
server.bindAsync('0.0.0.0:50051', grpc.ServerCredentials.createInsecure(), () => { console.log('服务器已在端口 50051 启动');});客户端(基于 TypeScript 的 gRPC 客户端)
创建文件 client.ts:
import * as grpc from '@grpc/grpc-js';import * as protoLoader from '@grpc/proto-loader';import { ProtoGrpcType } from './generated/hello';
const packageDef = protoLoader.loadSync('hello.proto');const grpcObj = (grpc.loadPackageDefinition(packageDef) as unknown) as ProtoGrpcType;
const client = new grpcObj.hello.Greeter( 'localhost:50051', grpc.credentials.createInsecure());
// 一元调用client.SayHello({ name: '爱丽丝' }, (err, response) => { if (!err) console.log('响应:', response?.message);});
// 服务器流式调用const stream = client.SayHelloStream({ name: '鲍勃' });stream.on('data', (data) => console.log('流:', data.message));stream.on('end', (