Golang用Proto文件同時生成gRPC和HTTP
大家好,我是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 哥和你主要聊一下其中可能會遇到的卡點。畢竟國內的網絡情況你懂的,有些操作可能會遇到一些困難。
1.不會科學上網不要用buf
教程里提供了兩種來操作,一種是通過基礎工具 protoc 來操作,另一種是通過一個基于 protoc 封裝的工具 buf 來操作。protoc 可以基于 go mod 來安裝,鑒于 go mod 還有國內的鏡像站點可以解決訪問的困難,建議不會科學上網的小伙伴通過 protoc 來操作,因為你沒辦法成功安裝 buf。
2.手動下載 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
3.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 文檔。
如此不但可以提高效率,還可以避免維護兩份不同的契約文件所帶來不一致風險,希望對你有所幫助。