Golang用Proto文件同時生成gRPC和HTTP
大家好,我是Z哥。
做技術(shù)的都知道,程序之間的通訊,常用的方式有兩種,RPC 和 HTTP。普遍的共識是系統(tǒng)內(nèi)部的各個子系統(tǒng)之間的通訊用 RPC,與外部系統(tǒng)之間的通訊用 HTTP。
為了避免需要分別編寫兩套契約文件來生成兩套 API(.proto 和 .api),如果能夠根據(jù)同一份契約文件生成兩套 API 的代碼就太棒了。
Z哥目前所在的公司,rpc 使用的框架是 gRPC,所以自然先想得是,是否能夠根據(jù)一份 proto 文件,同時生成 gRPC 和 HTTP 的 stub 代碼呢。
網(wǎng)上很快就找到了一個符合要求的框架。相信不少 gopher 們應(yīng)該也聽說過或者正在使用。
https://github.com/grpc-ecosystem/grpc-gateway
框架的原理用一張圖即可表達。
通過一份 proto 文件,在生成 gRPC 代碼的同時生成一個基于 HTTP1.1 + JSON 的反向代理 gateway,如此一來,既可以通過 gRPC 的方式直接調(diào)用實際的 server ,也可以通過反向代理中轉(zhuǎn)一次來訪問 server。
具體的使用方式看 github 上的官方教程即可,Z 哥和你主要聊一下其中可能會遇到的卡點。畢竟國內(nèi)的網(wǎng)絡(luò)情況你懂的,有些操作可能會遇到一些困難。
1.不會科學(xué)上網(wǎng)不要用buf
教程里提供了兩種來操作,一種是通過基礎(chǔ)工具 protoc 來操作,另一種是通過一個基于 protoc 封裝的工具 buf 來操作。protoc 可以基于 go mod 來安裝,鑒于 go mod 還有國內(nèi)的鏡像站點可以解決訪問的困難,建議不會科學(xué)上網(wǎng)的小伙伴通過 protoc 來操作,因為你沒辦法成功安裝 buf。
2.手動下載 googleapis 的repo
然后,當你定義 gateway 的時候,需要引入一些 google 的 packages,怎么辦呢?直接去 github 上下載,具體地址是:
https://github.com/googleapis/googleapis
如果可以的話,建議把整個倉庫都下載下來,否則就單獨下載教程里提到的4個文件即可。
特別要注意的是,在 googleapis/google/目錄下缺少的 protobuf 相關(guān)文件需要到下面的 repo 里去下載,并且放到 googleapis/google/目錄下。
https://github.com/protocolbuffers/protobuf/tree/main/src/google/protobuf
3.protoc -I 指定查找目錄
官方教程里的 protoc -I . 只會查找當前命令執(zhí)行所在目錄的范圍,所以如果你下載的 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
如果還有其它目錄需要查找,那么繼續(xù)增加 -I 即可。
好了需要注意的點就是以上3個,官方教程中提到的三個命令可以一起執(zhí)行,這樣便可同時生成 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
關(guān)于一些gRPC-Gateway的其它用法可以參考:
https://grpc-ecosystem.github.io/grpc-gateway/
好了,這篇呢,Z哥和你分享了如何用一份 proto 文件同時生成 gRPC 和 HTTP 的 Stub 代碼以及 Swagger 文檔。
如此不但可以提高效率,還可以避免維護兩份不同的契約文件所帶來不一致風險,希望對你有所幫助。