vlambda博客
学习文章列表

Golang用proto文件同时生成gRPC和HTTP

每周五11:45 按时送达

当然了,也会时不时加个餐~

我的第「224」篇原创敬上



大家好,我是Z哥。

做技术的都知道,程序之间的通讯,常用的方式有两种,RPC 和 HTTP。普遍的共识是系统内部的各个子系统之间的通讯用 RPC,与外部系统之间的通讯用 HTTP。

为了避免需要分别编写两套契约文件来生成两套 API(.proto 和 .api),如果能够根据同一份契约文件生成两套 API 的代码就太棒了。

Z哥目前所在的公司,rpc 使用的框架是 gRPC,所以自然先想得是,是否能够根据一份 proto 文件,同时生成 gRPC 和 HTTP 的 stub 代码呢。

网上很快就找到了一个符合要求的框架。相信不少 gopher 们应该也听说过或者正在使用。

https://github.com/grpc-ecosystem/grpc-gateway


框架的原理用一张图即可表达。


通过一份 proto 文件,在生成 gRPC 代码的同时生成一个基于 HTTP1.1 + JSON 的反向代理 gateway,如此一来,既可以通过 gRPC 的方式直接调用实际的 server ,也可以通过反向代理中转一次来访问 server。

具体的使用方式看 github 上的官方教程即可,Z 哥和你主要聊一下其中可能会遇到的卡点。毕竟国内的网络情况你懂的,有些操作可能会遇到一些困难。


/01  不会科学上网不要用buf/

教程里提供了两种来操作,一种是通过基础工具 protoc 来操作,另一种是通过一个基于 protoc 封装的工具 buf 来操作。protoc 可以基于 go mod 来安装,鉴于 go mod 还有国内的镜像站点可以解决访问的困难,建议不会科学上网的小伙伴通过 protoc 来操作,因为你没办法成功安装 buf。


/02  手动下载 googleapis 的repo/

然后,当你定义 gateway 的时候,需要引入一些 google 的 packages,怎么办呢?直接去 github 上下载,具体地址是:

https://github.com/googleapis/googleapis


如果可以的话,建议把整个仓库都下载下来,否则就单独下载教程里提到的4个文件即可。

特别要注意的是,在 googleapis/google/目录下缺少的 protobuf 相关文件需要到下面的 repo 里去下载,并且放到 googleapis/google/目录下。

https://github.com/protocolbuffers/protobuf/tree/main/src/google/protobuf


/03  protoc -I 指定查找目录/

官方教程里的 protoc -I . 只会查找当前命令执行所在目录的范围,所以如果你下载的 googlesapi 不存放在当前目录下,则需要增加额外信息指定一下查找目录。

指定的方式是再增加一个 -I,命令如下(其中第二行就是新增的用于查找 google packages 的目录):

protoc -I ./ \ -I $GOPATH/src/googleapis\ --grpc-gateway_out ./gen/go \ --grpc-gateway_opt logtostderr=true \ --grpc-gateway_opt paths=source_relative \ --grpc-gateway_opt generate_unbound_methods=true \ your/service/v1/your_service.proto

如果还有其它目录需要查找,那么继续增加 -I 即可。


好了需要注意的点就是以上3个,官方教程中提到的三个命令可以一起执行,这样便可同时生成 gRPC server、gateway 和 swagger.json :

protoc -I ./ \ -I $GOPATH/src/googleapis\ --go_out ./gen/go/ --go_opt paths=source_relative \ --go-grpc_out ./gen/go/ --go-grpc_opt paths=source_relative \ --grpc-gateway_out ./gen/go/ \ --grpc-gateway_opt logtostderr=true \ --grpc-gateway_opt paths=source_relative \ --grpc-gateway_opt generate_unbound_methods=true \ --openapiv2_out . --openapiv2_opt logtostderr=true \ your/service/v1/your_service.proto

关于一些gRPC-Gateway的其它用法可以参考:

https://grpc-ecosystem.github.io/grpc-gateway/


好了,这篇呢,Z哥和你分享了如何用一份 proto 文件同时生成 gRPC 和 HTTP 的 Stub 代码以及 Swagger 文档。

如此不但可以提高效率,还可以避免维护两份不同的契约文件所带来不一致风险,希望对你有所帮助。



推荐阅读:




原创不易,如果你觉得这篇文章还不错,就「点赞」或者「在看」一下吧,鼓励我的创作 :)


如果你有关于软件架构、分布式系统、产品、运营的困惑

可以试试点击「阅读原文」