gRPC 用于 TypeScript:库、配置和代码示例

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

gRPC 用于 TypeScript:库和示例



gRPC 是一个由 Google 开发的现代高性能远程过程调用(RPC)框架。它使用 Protocol Buffers(protobuf)作为接口定义语言和数据序列化格式。在 TypeScript 中,gRPC 通过 @grpc/grpc-js(用于服务器和客户端逻辑)和 protobufjs(用于处理 .proto 文件)包实现。在本文中,我们将介绍关键库、环境配置,并编写一个 TypeScript 工作示例。



TypeScript 中 gRPC 的关键库



  • @grpc/grpc-js — 纯 JavaScript 实现的 gRPC(无 C++ 插件)。支持所有主要功能:一元调用、服务器和客户端流式传输、双向流式传输。
  • protobufjs — 用于加载、解析和从 .proto 文件生成类的库。允许动态创建消息和服务。
  • @grpc/proto-loader — 辅助包,简化 proto 文件的加载,并根据定义自动生成 TypeScript 类型。
  • ts-protoc-gen — 用于 protoc 编译器的代码生成器。允许从 .proto 文件生成强类型类和接口。


对于大多数项目,@grpc/grpc-js + @grpc/proto-loader 的组合就足够了。如果需要最大程度的类型安全,可以使用 ts-protoc-gen 或 protobufjs 生成静态类型。



安装依赖项



创建一个新项目并安装必要的包:



mkdir grpc-typescript-examplecd grpc-typescript-examplenpm init -ynpm install @grpc/grpc-js @grpc/proto-loadernpm install -D typescript @types/nodenpx tsc --init


创建 proto 文件



定义一个简单的用户服务。创建文件 user.proto:



syntax = "proto3";

package user;

service UserService { rpc GetUser (GetUserRequest) returns (User); rpc ListUsers (ListUsersRequest) returns (stream User);}

message GetUserRequest { int32 id = 1;}

message ListUsersRequest { int32 page = 1; int32 limit = 2;}

message User { int32 id = 1; string name = 2; string email = 3;}


在 TypeScript 中实现 gRPC 服务器



创建文件 server.ts:



import * as grpc from '@grpc/grpc-js';import * as protoLoader from '@grpc/proto-loader';import path from 'path';

const PROTO_PATH = path.join(__dirname, 'user.proto');

const packageDefinition = protoLoader.loadSync(PROTO_PATH, { keepCase: true, longs: String, enums: String, defaults: true, oneofs: true,});

const userProto = grpc.loadPackageDefinition(packageDefinition) as any;

// 模拟数据库const users = [ { id: 1, name: 'Alice', email: 'alice@example.com' }, { id: 2, name: 'Bob', email: 'bob@example.com' },];

function getUser( call: grpc.ServerUnaryCall<{ id: number }, any>, callback: grpc.sendUnaryData<any>) { const user = users.find(u => u.id === call.request.id); if (!user) { return callback({ code: grpc.status.NOT_FOUND, message: 'User not found', }); } callback(null, user);}

function listUsers(call: grpc.ServerWritableStream<{ page: number; limit: number }, any>) { const page = call.request.page || 1; const limit = call.request.limit || 10; const start = (page - 1) * limit; const end = start + limit; const paginatedUsers = users.slice(start, end); paginatedUsers.forEach(user => call.write(user)); call.end();}

function main() { const server = new grpc.Server();

推荐