grpc-gateway 教程:用 Protocol Buffers 定义并运行一个 gRPC Hello World 服务
发布时间:2026/9/13 18:25:58 作者:尧图编辑部 阅读量:1,286

grpc-gateway 教程用 Protocol Buffers 定义并运行一个 gRPC Hello World 服务【免费下载链接】grpc-gatewaygRPC to JSON proxy generator following the gRPC HTTP spec项目地址: https://gitcode.com/GitHub_Trending/gr/grpc-gateway本教程是 grpc-gateway 入门系列的第一篇实战文章目标是让你从零开始、仅用一个.proto文件定义出一个可被 gRPC 与 HTTP/JSON 双协议访问的 Hello World 服务。读完本文后你将掌握 proto3 语法下service/message/rpc的定义方式、Greeter服务的标准写法并能结合仓库中的真实示例与生成代码理解 gRPC-Gateway 反向代理的生成原理为后续添加google.api.http注解、生成 stub 与编写网关入口main.go打好基础。为什么先写一个 Hello World gRPC 服务gRPC-Gateway 不是一个独立的运行时框架而是 Google Protocol Buffers 编译器protoc的一个插件它读取.proto服务定义根据服务中的google.api.http注解生成一个把 RESTful HTTP API 翻译成 gRPC 调用的反向代理服务器见 docs/docs/tutorials/introduction.md。也就是说一切代码生成都从.proto文件开始。在给服务加上 HTTP 映射注解之前我们必须先掌握如何用协议缓冲区定义出一个纯粹的、可独立运行的 gRPC 服务。这正是本文的核心HelloRequest、HelloReply两个消息加上一个SayHello()方法就构成了 gRPC 世界里最经典的“Hello World”。定义 gRPC 服务创建 hello_world.proto按教程约定我们在proto/helloworld/目录下创建hello_world.proto文件路径为proto/helloworld/hello_world.proto内容如下syntax proto3; package helloworld; // The greeting service definition service Greeter { // Sends a greeting rpc SayHello (HelloRequest) returns (HelloReply) {} } // The request message containing the users name message HelloRequest { string name 1; } // The response message containing the greetings message HelloReply { string message 1; }这份文件虽然短却包含了 proto3 的四个核心语法要素语法要素示例作用syntax proto3;文件首行声明使用 proto3 语法版本packagepackage helloworld;定义命名空间避免跨文件消息名冲突serviceservice Greeter { ... }声明一个 gRPC 服务内部包含 RPC 方法messagemessage HelloRequest定义请求 / 响应消息结构字段带编号field number其中rpc SayHello (HelloRequest) returns (HelloReply) {}声明了一个一元 RPCunary RPC客户端传入HelloRequest服务端返回HelloReply。字段后的数字 1是字段编号在 proto3 中用于二进制编码标识一旦发布就不应更改。对于 proto3 语法细节如字段类型、重复字段、嵌套消息等的深入讲解可以参考 Google Protocol Buffers 官方文档及其 Go 语言入门教程对本系列而言你只需理解服务端和客户端 stub 都会拥有一个SayHello()方法入参是HelloRequest出参是HelloReply这与后续在 Go 代码中实现该接口的方式一一对应。从仓库实例看完整的 proto 定义注解、类型与附加绑定教程中的hello_world.proto是刻意精简的教学版本。而在 grpc-gateway 仓库内部examples/internal/helloworld/helloworld.proto提供了一个加了 gRPC-Gateway 注解的真实版本能让你提前看到从纯 gRPC 到 HTTP/JSON 的差距syntax proto3; package grpc.gateway.examples.internal.helloworld; import google/api/annotations.proto; import google/protobuf/wrappers.proto; option go_package github.com/grpc-ecosystem/grpc-gateway/v2/examples/internal/helloworld; service Greeter { rpc SayHello(HelloRequest) returns (HelloReply) { option (google.api.http) { get: /say/{name} additional_bindings: {get: /say/strval/{strVal}} additional_bindings: {get: /say/floatval/{floatVal}} additional_bindings: {get: /say/boolval/{boolVal}} additional_bindings: {get: /say/int64val/{int64Val}} }; } } message HelloRequest { string name 1; google.protobuf.StringValue strVal 2; google.protobuf.FloatValue floatVal 3; google.protobuf.DoubleValue doubleVal 4; google.protobuf.BoolValue boolVal 5; google.protobuf.BytesValue bytesVal 6; google.protobuf.Int32Value int32Val 7; google.protobuf.UInt32Value uint32Val 8; google.protobuf.Int64Value int64Val 9; google.protobuf.UInt64Value uint64Val 10; } message HelloReply { string message 1; }为简洁起见上面示例省略了仓库原文件中的部分additional_bindings完整内容请直接查看 examples/internal/helloworld/helloworld.proto。这个真实示例相比教程版本多出三个关键点它们正是下一阶段“添加注解”的核心内容import google/api/annotations.proto只有引入了该文件才能在 RPC 上使用google.api.http注解。这是 gRPC-Gateway 识别 HTTP 映射的唯一入口。option (google.api.http) { get: /say/{name} ... }把SayHello映射到GET /say/{name}{name}花括号语法表示从 URL 路径中提取名为name的参数并填入HelloRequest.nameadditional_bindings则允许同一个 RPC 绑定多条额外的 HTTP 路径。wrapper 类型字段google.protobuf.StringValue、FloatValue等包装类型wrappers允许在 JSON 中表达“字段是否存在”与“值为 null”的语义examplepb等其它示例 proto 文件中也有类似用法。生成代码长什么样以仓库的 helloworld.pb.gw.go 为例定义好.proto并运行生成器后会得到若干*.pb.go与*.pb.gw.go文件。仓库中已经提交了生成产物可以直接阅读来验证“proto 定义 → 代码”的映射关系examples/internal/helloworld/helloworld.pb.go消息类型HelloRequest/HelloReply的 Go 结构体与编解码实现examples/internal/helloworld/helloworld_grpc.pb.goGreeterServer服务端接口与GreeterClient客户端 stubexamples/internal/helloworld/helloworld.pb.gw.go由 protoc-gen-grpc-gateway 生成的“反向代理”代码文件头注释明确写着Code generated by protoc-gen-grpc-gateway. DO NOT EDIT.包注释为 “It translates gRPC into RESTful JSON APIs.”。以helloworld.pb.gw.go为例可以清楚看到 HTTP 请求是如何被翻译成 gRPC 调用的见 examples/internal/helloworld/helloworld.pb.gw.gofunc request_Greeter_SayHello_0(ctx context.Context, marshaler runtime.Marshaler, client GreeterClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { // ... val, ok : pathParams[name] if !ok { return nil, metadata, status.Errorf(codes.InvalidArgument, missing parameter %s, name) } protoReq.Name, err runtime.String(val) // ... }关键点在于pathParams[name]它正是从GET /say/{name}的路径模板中解析出来的name参数随后被runtime.String(val)转换为字符串并填入HelloRequest.Name。可见路径参数到 gRPC 请求消息的填充逻辑完全是由生成器自动产出的开发者无需手写任何 HTTP 解析代码。再看服务注册入口同上文件约 804 行附近func RegisterGreeterHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error { return RegisterGreeterHandlerClient(ctx, mux, NewGreeterClient(conn)) }它接受一个已拨通的grpc.ClientConn把 HTTP handler 注册到runtime.ServeMux上。这个函数正是下一篇教程docs/docs/tutorials/creating_main.go.md中main.go里调用的helloworldpb.RegisterGreeterHandler(...)——到时你会看到完整的调用链HTTP 请求 → ServeMux → 生成的反向代理 → gRPC ClientConn → gRPC 服务端。从 Hello World 到 gRPC-Gateway本教程在整个系列中的位置按官方教程的导航顺序docs/docs/tutorials/index.md本系列共分五步本文是第一站本文用 proto 定义Greeter/SayHello先让纯 gRPC 服务跑通generating_stubs/index.md用protoc或buf生成 Go stubcreating_main.go.md编写 Go gRPC 服务端main.go实现SayHello并注册到 gRPC serveradding_annotations.md给SayHello添加google.api.http注解如post: /v1/example/echo、body: *再生成*.gw.pb.go并注册 gRPC-Gateway muxlearn_more.md深入学习后续内容。也就是说本文定义的 proto 文件在后续步骤中会被反复修改和重新生成先加 HTTP 注解再生成 stub最后用go run main.go启动双协议服务并用curl -X POST http://localhost:8090/v1/example/echo -d {name: hello}得到{message:hello world}的 JSON 响应。整个过程印证了 gRPC-Gateway 的设计哲学只在.proto文件中编写一次服务定义就能同时获得 gRPC 与 HTTP/JSON 两种 API出处docs/docs/tutorials/introduction.md。动手前的准备前置工具与 go.mod 初始化虽然本文只涉及 proto 定义但为了后续步骤能顺利执行建议先按 docs/docs/tutorials/introduction.md 完成环境准备安装 Go教程示例使用 Go 编写 gRPC 服务安装三个 protoc 生成器插件需确保$GOPATH/bin在$PATH中$ go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gatewaylatest $ go install google.golang.org/protobuf/cmd/protoc-gen-golatest $ go install google.golang.org/grpc/cmd/protoc-gen-go-grpclatest在工作目录初始化模块$ go mod init github.com/myuser/myrepo go: creating new go.mod: module github.com/myuser/myrepo教程使用github.com/myuser/myrepo作为模块路径占位符实际生产代码中应替换为你的模块可被下载的 URL。后续main.go中会以helloworldpb github.com/myuser/myrepo/proto/helloworld的形式导入本教程生成的包见 docs/docs/tutorials/creating_main.go.md。小结与下一步通过本文你已经完成了 gRPC-Gateway 入门的第一步掌握 proto3 中service/rpc/message的基本定义语法理解HelloRequest入参与HelloReply出参在服务端、客户端 stub 中的对应关系通过仓库中的 examples/internal/helloworld/helloworld.proto 与 examples/internal/helloworld/helloworld.pb.gw.go提前看到注解、wrapper 类型与反向代理生成代码的全貌。接下来请进入系列第二步 生成 stubgenerating_stubs选择protoc或buf其中一种方式把本文件定义的Greeter服务编译为 Go 代码随后按 creating_main.go.md 编写服务端实现再按 adding_annotations.md 为SayHello挂上 HTTP 映射一个同时支持 gRPC 与 HTTP/JSON 的 Hello World 服务就真正跑起来了。【免费下载链接】grpc-gatewaygRPC to JSON proxy generator following the gRPC HTTP spec项目地址: https://gitcode.com/GitHub_Trending/gr/grpc-gateway创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考