ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

FlatBuffers 与 gRPC 的 TypeScript 实践:跑通 greeter 服务端与客户端

2026/9/20 13:21:26 拓冰建站 浏览量
FlatBuffers 与 gRPC 的 TypeScript 实践:跑通 greeter 服务端与客户端 序列化跨平台编译器【免费下载链接】flatbuffersFlatBuffers: Memory Efficient Serialization Library项目地址https://gitcode.com/gh_mirrors/flat/flatbuffers点击查看免费下载FlatBuffers 是一种零拷贝、内存高效的序列化库而 gRPC 是基于 HTTP/2 的跨语言 RPC 框架。本指南以仓库中 grpc/examples/ts/greeter 示例为蓝本完整讲解如何在 TypeScript 环境中用 FlatBuffers 作为 gRPC 的传输载荷从编译构建、启动服务端到调用一元 RPCUnary与服务端流式 RPCServer Streaming的完整链路。读完本文你将能够在本仓库中直接运行 TS gRPC 示例并理解其背后的 schema 定义、代码生成与序列化原理。示例概览该示例演示了一个典型的 Greeter 服务客户端发送一个包含name字段的HelloRequest服务端返回包含message字段的HelloReply。它同时展示了 gRPC 的两种调用模式一元 RPCUnarySayHello—— 请求与响应均为单条消息服务端流式 RPCServer StreamingSayManyHellos—— 单个请求返回多条响应消息。整个示例的目录结构如下grpc/examples/ts/greeter/ ├── README.md # 官方运行说明本文核心依据 ├── package.json # npm 脚本与依赖声明 ├── tsconfig.json # TypeScript 编译配置 └── src/ ├── client.ts # gRPC 客户端入口 ├── server.ts # gRPC 服务端入口 ├── greeter.ts # 生成的 FlatBuffers 模型聚合导出 ├── greeter_generated.ts # 生成的模型代码 ├── greeter_grpc.js # 生成的 gRPC 服务定义与客户端构造器 ├── greeter_grpc.d.ts # 生成的 gRPC 类型声明 ├── models.ts # 模型命名空间导出 └── models/ ├── hello-reply.ts # HelloReply 表生成代码 └── hello-request.ts # HelloRequest 表生成代码前置条件根据 README.md 的说明运行该示例前需要确保本机已安装TypeScript。示例依赖通过 package.json 声明{ name: flatbuffers-js-grpc, version: 1.0.0, scripts: { build: npm install tsc, client: node dist/client.js, server: node dist/server.js }, dependencies: { grpc/grpc-js: ^1.3.2, flatbuffers: ^2.0.0 } }grpc/grpc-js纯 JavaScript 实现的 gRPC 运行时负责 HTTP/2 传输、服务注册与调用分发flatbuffersFlatBuffers 官方 TypeScript 运行时提供Builder、ByteBuffer等序列化基础组件。脚本说明npm run build会先执行npm install安装依赖再执行tsc将src/下的 TypeScript 编译到dist/npm run server与npm run client分别启动编译后的服务端与客户端。编译构建进入示例目录后两种方式均可完成构建# 方式一官方脚本自动完成依赖安装与编译 npm run build # 方式二分步执行 npm install tsctsc依据 tsconfig.json 进行编译关键配置项如下{ compilerOptions: { target: es5, module: commonjs, outDir: ./dist, allowJs: true, sourceMap: true, strict: true, esModuleInterop: true, baseUrl: ./ } }其中outDir: ./dist指定编译产物输出目录allowJs: true允许直接引入仓库中已有的 JS 文件如greeter_grpc.jsstrict: true开启严格类型检查以保证示例代码的类型安全。构建完成后服务端与客户端脚本分别位于dist/server.js与dist/client.js。启动服务端npm run server服务端逻辑位于 src/server.ts。其核心流程如下实现服务接口定义一个greeter对象实现IGreeterServer接口中的SayHello与SayManyHellos两个方法创建并绑定服务实例化grpc.Server通过server.addService(GreeterService, greeter)将生成的服务定义与实现绑定监听端口调用server.bindAsync(localhost:3000, grpc.ServerCredentials.createInsecure(), ...)绑定端口并启动。服务端固定监听localhost:3000使用不加密的createInsecure()凭据适用于本地开发调试。SayHello一元 RPC 实现SayHello(call: grpc.ServerUnaryCallHelloRequest, HelloReply, callback: grpc.sendUnaryDataHelloReply): void { console.log(SayHello ${call.request.name()}); const builder new flatbuffers.Builder(); const offset builder.createString(welcome ${call.request.name()}); const root HelloReply.createHelloReply(builder, offset); builder.finish(root); callback(null, HelloReply.getRootAsHelloReply(new flatbuffers.ByteBuffer(builder.asUint8Array()))); }实现要点通过call.request.name()读取请求中的 FlatBuffers 字段注意这里直接是访问器调用而非属性访问构造响应时创建flatbuffers.Builder用createString写入字符串、HelloReply.createHelloReply组装表结构、builder.finish完成缓冲最后将builder.asUint8Array()包装为flatbuffers.ByteBuffer后通过HelloReply.getRootAsHelloReply取根对象传给callback完成响应返回。SayManyHellos服务端流式 RPC 实现async SayManyHellos(call: grpc.ServerWritableStreamHelloRequest, HelloReply): Promisevoid { const name call.request.name(); [Hi, Hallo, Ciao].forEach(element { const builder new flatbuffers.Builder(); const offset builder.createString(${element} ${name}); const root HelloReply.createHelloReply(builder, offset); builder.finish(root); call.write(HelloReply.getRootAsHelloReply(new flatbuffers.ByteBuffer(builder.asUint8Array()))); }); call.end(); }与一元 RPC 的区别在于响应通过call.write(...)多次写入此处为 Hi、Hallo、Ciao 三种问候语最后调用call.end()结束流。每个响应消息都独立构建一次 FlatBuffers 缓冲。启动客户端npm run client 3000README 中的3000是客户端第一个命令行参数即服务端监听端口。客户端逻辑位于 src/client.ts其参数解析如下const args process.argv.slice(2); const PORT Number(args[0]); // 第一个参数端口号必填 const name: string args[1] ?? flatbuffers; // 第二个参数name 字段可选默认 flatbuffers若未提供有效的端口号客户端会抛出Requires a valid port number.错误。客户端主流程async function main(PORT: Number, name: string) { const client new GreeterClient(localhost:${PORT}, grpc.credentials.createInsecure()); const builder new flatbuffers.Builder(); const offset builder.createString(name); const root HelloRequest.createHelloRequest(builder, offset); builder.finish(root); const buffer HelloRequest.getRootAsHelloRequest(new flatbuffers.ByteBuffer(builder.asUint8Array())); client.SayHello(buffer, (err, response) { console.log(response.message()); }); const data client.SayManyHellos(buffer, null); data.on(data, (data) { console.log(data.message()); }); }这里可以看到 FlatBuffers 的核心使用范式先构建Builder→ 再读取ByteBuffer getRootAs。请求以 FlatBuffers 二进制形式序列化后直接传给 gRPC 方法对于流式调用SayManyHellos返回一个可读流对象通过data.on(data, ...)逐条消费服务端推送的问候消息。底层原理schema 定义与代码生成服务定义.fbs 文件示例的接口契约定义在 grpc/examples/greeter.fbs注意该 schema 位于grpc/examples/目录下供多语言示例共用namespace models; table HelloReply { message:string; } table HelloRequest { name:string; } rpc_service Greeter { SayHello(HelloRequest):HelloReply; SayManyHellos(HelloRequest):HelloReply (streaming: server); }要点解析table定义消息结构字段为字符串类型rpc_service Greeter声明 RPC 服务方法参数与返回值直接使用 FlatBuffers 表(streaming: server)元数据声明SayManyHellos为服务端流式方法即请求一条、响应多条。这一声明是后续生成responseStream: true的源头。生成的 gRPC 粘合代码sr c/greeter_grpc.js 是 FlatBuffers 编译器为 gRPC 生成的粘合代码文件头标注 Generated GRPC code for FlatBuffers TS *** DO NOT EDIT ***其中serialize_models_HelloReply/deserialize_models_HelloReply等函数负责在 gRPC 字节流与 FlatBuffers 对象间转换序列化直接使用Buffer.from(buffer_args.serialize())反序列化则通过getRootAsHelloReply(new flatbuffers.ByteBuffer(buffer))完成GreeterService导出完整的ServiceDefinition其中SayHello的requestStream: false, responseStream: false一元而SayManyHellos的responseStream: true服务端流式GreeterClient由grpc.makeGenericClientConstructor(GreeterService)动态构造因此客户端无需手写任何 RPC 调用代码。对应的类型声明 src/greeter_grpc.d.ts 提供了IGreeterServer、IGreeterClient等接口这正是 src/server.ts 中const greeter: IGreeterServer {...}能获得类型检查的原因——SayHello被声明为grpc.handleUnaryCallSayManyHellos被声明为grpc.handleServerStreamingCall与运行时行为严格对应。生成的模型代码src/models/hello-request.ts 与 src/models/hello-reply.ts 是编译器生成的 FlatBuffers 表模型每个类提供读取侧getRootAsHelloRequest/getRootAsHelloReply从ByteBuffer定位根对象name()/message()访问器按需解码字段通过__offset惰性读取体现零拷贝特性构建侧startXxx/addXxx/endXxx/createXxx静态方法配合flatbuffers.Builder完成序列化传输侧serialize()返回底层Uint8Arraydeserialize()反向还原被 gRPC 粘合代码直接使用。而 src/greeter.ts 仅一行export * as models from ./models.js用于将模型统一挂到models命名空间下与 schema 中的namespace models;一一对应。运行结果与验证按顺序执行以下命令即可看到完整交互cd grpc/examples/ts/greeter npm run build # 安装依赖并编译到 dist/ npm run server # 终端 A启动服务端输出 Listening on 3000 / Server bound on port: 3000 # 另开终端在示例目录下执行 npm run client 3000 # 使用默认 name flatbuffers npm run client 3000 Alice # 自定义 name客户端控制台会依次输出welcome flatbuffers # SayHello 的一元响应 Hi flatbuffers # SayManyHellos 流式响应第 1 条 Hallo flatbuffers # 第 2 条 Ciao flatbuffers # 第 3 条服务端控制台则会打印收到的请求名SayHello ...与... saying hi in different langagues与客户端日志形成一一对应的验证闭环。小结与扩展本示例展示了 FlatBuffers 与 gRPC 在 TypeScript 生态中的标准集成方式以.fbsschema 声明消息与服务经编译器生成模型代码与 gRPC 粘合代码运行时借助grpc/grpc-js完成传输而 FlatBuffers 的Builder/ByteBuffer全程负责高效序列化与零拷贝读取。由于传输的始终是紧凑的二进制缓冲该方案在需要低内存占用、低解析开销的微服务场景中尤为适用。如需继续深入可参考仓库中的相关资源grpc/README.mdgRPC 支持的总体说明与多语言示例索引grpc/examples/ts/greeter/src/server.ts 与 grpc/examples/ts/greeter/src/client.ts本文分析的服务端/客户端完整实现grpc/examples/greeter.fbs示例的 schema 契约定义grpc/src/compilerFlatBuffers gRPC 代码生成器的 C 实现tests/tsTypeScript 相关的测试目录可参考更多调用范式。赞分享序列化跨平台编译器【免费下载链接】flatbuffersFlatBuffers: Memory Efficient Serialization Library项目地址https://gitcode.com/gh_mirrors/flat/flatbuffers点击查看免费下载相关推荐FlatBuffers 与 gRPC 的 TypeScript 实践Greeter 示例服务端与客户端完整运行指南FlatBuffers 与 gRPC 的 TypeScript 实践Greeter 示例服务端与客户端完整运行指南 本指南以仓库中 grpc/examples序列化代码生成FlatBuffers Go gRPC Greeter 示例从 .fbs 定义到可运行的服务端与客户端FlatBuffers Go gRPC Greeter 示例从 .fbs 定义到可运行的服务端与客户端 本篇技术指南以仓库中 grpc/examples/go序列化代码生成在 C 中使用 FlatBuffers 构建 gRPC 服务从 Schema 到客户端与服务端的完整实战指南在 C 中使用 FlatBuffers 构建 gRPC 服务从 Schema 到客户端与服务端的完整实战指南 导读 FlatBuffers 是一种免解析人工智能推理引擎深度学习本地部署大模型上一篇Astrofox 开源项目教程下一篇SVG加载动画精灵n3r4zzurr0/svg-spinners完全指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考