首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >Go 语言微服务框架 Kratos 是怎么让 gRPC 自动变成 REST 接口的?

Go 语言微服务框架 Kratos 是怎么让 gRPC 自动变成 REST 接口的?

作者头像
frank.
发布2025-11-12 16:23:20
发布2025-11-12 16:23:20
1020
举报

01 、介绍

Kratos 官方提供了 protoc-gen-go-http 插件,该插件根据 .proto 文件中的 google.api.http option,生成 HTTP handler、路由注册代码、参数绑定逻辑。

与 grpc-gateway 不同,protoc-gen-go-http 并不需要额外的“网关”层。它直接在服务端生成原生的 http.Handler,让 gRPC 服务天然具备 REST 能力。

02google.api.http option 详解

google.api.http option 是 Google API 的一个 Protobuf 扩展,用来把 gRPC 方法映射为 HTTP REST 接口。

代码语言:javascript
复制
syntax = "proto3";

package helloworld.v1;

import"google/api/annotations.proto";

// The greeting service definition.
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply) {
    option (google.api.http) = {
      get: "/helloworld/{name}"
      // 可以添加附加接口
      additional_bindings {
          // 定义一个 POST 接口,并且把 body 映射到 HelloRequest
          post: "/v1/greeter/say_hello",
          body: "*",
      }
    };
  }
}

// The request message containing the user's name.
message HelloRequest {
string name = 1;
}

// The response message containing the greetings
message HelloReply {
string message = 1;
}

阅读上面这段代码,我们可以在 .proto 文件中添加 google.api.http option,其中,get: "/helloworld/{name}" 是把 name 映射到 URL 路径参数,即 /helloworld/frank

post: "/v1/greeter/say_hello" 定义一个 POST 请求方式的 API,body: "*" 代表整个请求体(JSON)映射到 HelloRequest

additional_bindings 可以让同一个 RPC 方法绑定多个 HTTP endpoint(GET/POST/PUT等)。

需要注意的是,如果希望通过 gRPC 服务自动生成 REST 接口,可以使用 Google 官方的 grpc-gateway 插件 protoc-gen-grpc-gateway,它会在 gRPC 服务前增加一层 HTTP 转发网关,将 HTTP 请求映射并转发到 gRPC 服务端。

相比之下,grpc-gateway 适合已有 gRPC 服务、希望兼容 REST 访问的场景;而 protoc-gen-go-http 则更偏向在 Kratos 中统一生成原生 gRPC + HTTP 服务代码,部署更轻量。

关于 grpc-gateway 的使用,我们在之前的文章「Golang 语言 gRPC 服务怎么同时支持 gRPC 和 HTTP 客户端调用?」中介绍过,本文不再赘述。

03 、在 Kratos 中使用 protoc-gen-go-http 插件

protoc-gen-go-http 插件是 Kratos 的一部分,它是 Kratos 官方开发和维护的,让我们可以通过 Protobuf IDL 同时生成 gRPC 服务和原生 HTTP 服务(基于 net/http),无需使用额外的 “网关”。

该插件的作用是根据 .proto 文件中的 google.api.http option,生成相应的 HTTP 适配层代码。具体来说,它会生成:

  • 一个 RegisterXXXHTTPServer(mux, server) 函数(用于把 gRPC 风格的服务注册为 HTTP handler)。
  • 一个接口 XXXHTTPServer,定义 HTTP 层方法签名。
  • 自动路由注册表(根据 google.api.http 选项里的路径映射)。

这些代码都是纯 Go 的,在生成的代码文件 api/helloworld/v1/greeter_http.pb.go 中,不依赖 grpc-gateway 或任何中间层。

理论讲完了,接下来我们进入实战环节:如何用 protoc-gen-go-http 生成可直接运行的 HTTP 服务代码。

安装插件:

在使用 protoc-gen-go-http 插件之前,我们先通过命令安装插件:

代码语言:javascript
复制
go install github.com/go-kratos/kratos/cmd/protoc-gen-go-http/v2@latest

生成代码:

在 Part 02 中,我们定义的 .proto 文件,可以使用 protoc,或者 make 命令,或者 Kratos 提供的 CLI 工具 kratos,生成 Client 和 Service 代码。

我们以 kratos cli 为例,代码如下:

生成 Client 代码:

代码语言:javascript
复制
kratos proto client api/helloworld/v1/greeter.proto

生成代码文件:

代码语言:javascript
复制
api/helloworld/v1/greeter.pb.go
api/helloworld/v1/greeter_grpc.pb.go
# 注意 http 代码只会在 proto 文件中声明了 http 时才会生成
api/helloworld/v1/greeter_http.pb.go

其中,api/helloworld/v1/greeter_http.pb.go 文件就是提供 REST API 的相关代码。

代码语言:javascript
复制
// ...
type GreeterHTTPServer interface {
 // SayHello Sends a greeting
 SayHello(context.Context, *HelloRequest) (*HelloReply, error)
}

func RegisterGreeterHTTPServer(s *http.Server, srv GreeterHTTPServer) {
 r := s.Route("/")
 r.POST("/v1/greeter/say_hello", _Greeter_SayHello0_HTTP_Handler(srv))
 r.GET("/helloworld/{name}", _Greeter_SayHello1_HTTP_Handler(srv))
}
// ...

04 、总结

protoc-gen-go-http 是 Kratos 在 gRPC 生态上的一次重要增强。

它让开发者可以在一份 .proto 文件中同时定义 gRPC 与 HTTP 接口,并自动生成服务代码,避免维护多套路由逻辑。

对于希望使用 Kratos 构建同时支持 gRPC + REST 的 Go 服务,这个插件几乎是“必备工具”。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-10-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Golang语言开发栈 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 01 、介绍
  • 04 、总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档