资讯动态

FlatBuffers Go gRPC Greeter 示例:从 .fbs 定义到可运行的服务端与客户端

发布时间:2026/9/11 22:06:20 来源:尧图企业网站定制
FlatBuffers Go gRPC Greeter 示例从 .fbs 定义到可运行的服务端与客户端【免费下载链接】flatbuffersFlatBuffers: Memory Efficient Serialization Library项目地址: https://gitcode.com/GitHub_Trending/fl/flatbuffers本篇技术指南以仓库中 grpc/examples/go/greeter/README.md 为核心完整讲解如何基于 FlatBuffers 构建一个 Go 语言的 gRPC 服务从编写greeter.fbs的 RPC 服务定义到生成 Go 模型代码与 gRPC 桩代码再到启动服务端、调用客户端的完整流程。读完本文你将掌握 FlatBuffers 作为 gRPC 序列化格式的接入方式、FlatbuffersCodec的编解码原理、一元 RPCSayHello与服务端流式 RPCSayManyHellos的完整实现细节并可直接在本地复现运行。示例整体结构与模块划分示例采用三模块布局与 README 中给出的目录结构一一对应grpc/examples/go/greeter/ ├── server # 服务端模块监听端口、注册 Greeter 服务 ├── client # 客户端模块构建 FlatBuffers 请求并调用 ├── models # FlatBuffers 模型代码与 gRPC 主代码由 flatc 生成 └── README.mdserver/main.gogRPC 服务端入口注册 Greeter 服务并监听localhost:3000client/main.gogRPC 客户端入口通过--name参数指定要发送的名字依次调用SayHello与SayManyHellosmodels/由 FlatBuffers 编译器flatc生成的HelloRequest.go、HelloReply.go以及 gRPC Go 插件生成的Greeter_grpc.go是服务端与客户端共享的公共代码。三个模块各自拥有独立的go.modclient与server都通过replace指令把models模块指向本地../models目录例如 server/go.mod 中的replace github.com/google/flatbuffers/grpc/examples/go/greeter/models v0.0.0 ../models这种方式避免了把生成的模型代码发布到远程仓库本地开发时直接复用同一份models包保证两端消息结构一致。服务定义greeter.fbs 中的 RPC 描述整个示例的业务协议定义在 grpc/examples/greeter.fbs 中namespace models; table HelloReply { message:string; } table HelloRequest { name:string; } rpc_service Greeter { SayHello(HelloRequest):HelloReply; SayManyHellos(HelloRequest):HelloReply (streaming: server); }从中可以看到 FlatBuffers 描述 gRPC 服务的三个关键语法要素table定义消息体HelloRequest携带一个name字符串字段HelloReply携带一个message字符串字段与常规 FlatBuffers schema 完全一致rpc_service关键字声明 gRPC 服务本例服务名为Greeter(streaming: server)标注SayHello是标准的一元 RPC一次请求、一次响应SayManyHellos声明为服务端流式 RPC客户端发送一次请求服务端可以连续推送多条HelloReply。在 grpc/examples/greeter_v2.fbs 中还有该服务的第二版本定义用于演示 Swift 等其他语言实现Go 示例使用的是上述greeter.fbs。生成模型代码models 模块的产物models目录下的三个文件是「生成代码 手写代码」协作的结果HelloRequest.go/HelloReply.go由flatc --go生成文件头标注 Code generated by the FlatBuffers compiler. DO NOT EDIT.Greeter_grpc.go由 gRPC Go 插件生成文件头标注 Generated by gRPC Go plugin其中RegisterGreeterServer、NewGreeterClient等正是服务端与客户端 main.go 直接调用的入口。HelloRequest 的读写接口以 models/HelloRequest.go 为例它展示了 FlatBuffers 生成的典型 API 形态GetRootAsHelloRequest(buf, offset)从字节缓冲区反序列化出请求对象HelloRequestStart(builder)/HelloRequestAddName(builder, name)/HelloRequestEnd(builder)使用flatbuffers.Builder从零构建一条请求Name()以[]byte形式读取name字段未设置时返回nil。Greeter 服务的 gRPC 桩models/Greeter_grpc.go 中与标准 gRPC 生成代码最大的不同在于消息类型接口方法签名直接使用*flatbuffers.Builder作为请求/响应载体而不是 protobuf 消息对象。例如type GreeterClient interface { SayHello(ctx context.Context, in *flatbuffers.Builder, opts ...grpc.CallOption) (*HelloReply, error) SayManyHellos(ctx context.Context, in *flatbuffers.Builder, opts ...grpc.CallOption) (Greeter_SayManyHellosClient, error) }服务端侧接口GreeterServer则反向使用*HelloRequest作为入参、*flatbuffers.Builder作为返回值type GreeterServer interface { SayHello(context.Context, *HelloRequest) (*flatbuffers.Builder, error) SayManyHellos(*HelloRequest, Greeter_SayManyHellosServer) error mustEmbedUnimplementedGreeterServer() }服务描述_Greeter_serviceDesc中注册了名为models.Greeter的服务SayHello走一元MethodDescSayManyHellos走服务端流式StreamDescServerStreams: true这正是greeter.fbs中两种 RPC 形态在生成代码层面的落点。运行服务端按照 README 的步骤在grpc/examples/go/greeter/server目录下执行cd server go clean go run main.go服务端启动后监听localhost:3000其启动逻辑集中在 server/main.go 的main()中核心只有三步监听 TCP 端口net.Listen(tcp, localhost:3000)注入 FlatBuffers 编解码器codec : flatbuffers.FlatbuffersCodec{} grpcServer : grpc.NewServer(grpc.ForceServerCodec(codec))这一行是整个示例的关键gRPC 默认使用 protobuf 编解码而grpc.ForceServerCodec强制服务端改用flatbuffers.FlatbuffersCodec从而让 gRPC 帧内直接承载 FlatBuffers 二进制实现零拷贝、无中间对象的高效传输 3.注册服务并启动models.RegisterGreeterServer(grpcServer, newServer())后调用grpcServer.Serve(lis)。SayHello一元 RPC 的服务端实现func (s *greeterServer) SayHello(ctx context.Context, request *models.HelloRequest) (*flatbuffers.Builder, error) { v : request.Name() var m string if v nil { m Unknown } else { m string(v) } b : flatbuffers.NewBuilder(0) idx : b.CreateString(welcome m) models.HelloReplyStart(b) models.HelloReplyAddMessage(b, idx) b.Finish(models.HelloReplyEnd(b)) return b, nil }实现细节值得注意通过request.Name()读取请求中的名字若字段为空则回退为Unknown体现 FlatBuffers 可选字段nil判断的惯用法响应不构造中间对象直接用flatbuffers.NewBuilder(0)逐字段写入HelloReply并Finish最终返回的是*flatbuffers.Builder而非序列化后的字节切片由 gRPC 框架配合FlatbuffersCodec完成后续写帧。SayManyHellos服务端流式 RPC 的实现for _, greeting : range greetings { // greetings [...]string{Hi, Hallo, Ciao} idx : b.CreateString(greeting m) models.HelloReplyStart(b) models.HelloReplyAddMessage(b, idx) b.Finish(models.HelloReplyEnd(b)) if err : stream.Send(b); err ! nil { return err } }服务端在单个请求内循环三次通过stream.Send(b)连续推送三条问候消息Hi、Hallo、Ciao体现服务端流式 RPC 的语义一次请求、多次响应直到函数返回。运行客户端按照 README 的步骤在grpc/examples/go/greeter/client目录下执行cd client go clean go run main.go --name NAME其中--name是客户端定义的命令行参数默认值为Flatbuffers来自 client/main.go 中的name flag.String(name, Flatbuffers, name to be sent to server :D)客户端连接与调用逻辑同样分为几步建立连接并指定编解码器conn, err : grpc.Dial(fmt.Sprintf(localhost:%d, 3000), grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithDefaultCallOptions(grpc.ForceCodec(flatbuffers.FlatbuffersCodec{})))服务端未配置 TLS因此客户端必须使用insecure.NewCredentials()否则握手会失败grpc.WithDefaultCallOptions(grpc.ForceCodec(...))与grpc.CallContentSubtype(flatbuffers)共同作用确保所有调用的请求/响应都按 FlatBuffers 编解码。构建请求并调用 SayHellob : flatbuffers.NewBuilder(0) i : b.CreateString(name) models.HelloRequestStart(b) models.HelloRequestAddName(b, i) b.Finish(models.HelloRequestEnd(b)) ctx, cancel : context.WithTimeout(context.Background(), 10*time.Second) defer cancel() request, err : client.SayHello(ctx, b, grpc.CallContentSubtype(flatbuffers)) log.Printf(server said %q, request.Message())请求的构建与服务端一致先CreateString创建字符串偏移再HelloRequestStart→HelloRequestAddName→HelloRequestEnd→Finish。调用时设置 10 秒超时上下文并把*flatbuffers.Builder直接作为请求参数传入。响应*HelloReply通过request.Message()读取服务端回写的问候语。消费服务端流 SayManyHellosstream, err : client.SayManyHellos(ctx, b, grpc.CallContentSubtype(flatbuffers)) for { request, err : stream.Recv() if err io.EOF { break } if err ! nil { log.Fatalf(...) } log.Printf(server said %q, request.Message()) }客户端循环调用stream.Recv()逐条接收服务端推送的消息直到收到io.EOF才结束——这是 gRPC Go 服务端流式客户端收包的标准写法。按默认参数运行客户端将依次收到三条问候server said welcome Flatbuffers server said Hi Flatbuffers server said Hallo Flatbuffers server said Ciao Flatbuffers依赖与 Go 版本要求三个模块的go.mod均声明go 1.15核心依赖为github.com/google/flatbuffers v2.0.8incompatibleFlatBuffers Go 运行时库提供flatbuffers.Builder、FlatbuffersCodec等google.golang.org/grpc v1.56.3gRPC Go 框架。client、server模块额外通过replace指令引用本地models模块。由于示例本身位于 FlatBuffers 仓库内直接go run时 Go 模块解析会命中仓库自身的依赖若将其复制到仓库外使用需要把github.com/google/flatbuffers替换为你实际引入的 FlatBuffers 版本路径。从零复现自己动手生成模型代码仓库中已提交生成好的models代码但如果你想从greeter.fbs重新生成例如修改了 schema流程是先构建flatcFlatBuffers 编译器参见 docs/building.md 中的构建说明在 grpc/examples 目录下执行flatc --go --grpc -o go/greeter/models greeter.fbs生成的HelloRequest.go、HelloReply.go与Greeter_grpc.go会写入models目录其中 gRPC 桩需要--grpc选项并链接 gRPC Go 插件。仓库还提供了批量重新生成的辅助脚本可参考 scripts/generate_grpc_examples.py 与 grpc/examples/go/format.sh后者用于对生成代码执行gofmt格式化。与仓库其他语言示例的对照同一份greeter.fbs在仓库中被翻译成了多种语言的完整示例可作为学习参照Python见 grpc/examples/python/greeter/README.md包含server.py/client.pySwift见 grpc/examples/swift/Greeter/README.mdTypeScript见 grpc/examples/ts/greeter/README.md。gRPC 的框架级测试则集中在 grpc/tests 目录其中 grpc/tests/grpctest.cpp 与 grpc/tests/grpctest.py 对FlatbuffersCodec在 C 与 Python 侧的接入做了系统性验证可作为深入理解编解码器实现与边界行为的补充材料。小结这个 Go Greeter 示例浓缩了 FlatBuffers 与 gRPC 集成的全部关键点用rpc_service在.fbs中声明服务、用flatc --grpc生成 Go 桩代码、在服务端与客户端两侧通过FlatbuffersCodec替换默认 protobuf 编解码并分别演示了一元 RPC 与服务端流式 RPC 的完整读写流程。理解它之后把现有 protobuf gRPC 服务迁移到 FlatBuffers 序列化或在新的 Go 服务中采用零拷贝传输方案都可以直接照搬这套结构。【免费下载链接】flatbuffersFlatBuffers: Memory Efficient Serialization Library项目地址: https://gitcode.com/GitHub_Trending/fl/flatbuffers创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价