1. 程式人生 > >go微服務系列(四) - http api中引入protobuf

go微服務系列(四) - http api中引入protobuf

- [1. protobuf相關依賴安裝](#head1) - [2. 改造之前的client](#head2) - [2.1 新建proto檔案](#head3) - [2.2 執行protoc命令生成go檔案](#head4) - [2.3 然後把原來的map修改成具體的型別就可以了](#head5) - [3. 處理json tag不一致的問題](#head6) ## 1. protobuf相關依賴安裝 - **第一步:下載grpc通用編譯器** 如下圖,解壓出來因平臺而異會是一個`protoc`或者`protoc.exe` > https://github.com/protocolbuffers/protobuf/releases ![](https://tva1.sinaimg.cn/large/007S8ZIlgy1ghn71b14sxj312l0g0di1.jpg) - **第二步:把下載的二進位制檔案路徑新增到環境變數中**(為了能全域性訪問protoc) - 這裡以為mac為例子 ```shell # 開啟這個 vim /etc/paths # 把路徑新增進去 /Users/emm/others/protoc-3.12.4-osx-x86_64/bin/protoc # 重新整理環境變數 source /etc/paths ``` - **第三步**: 安裝go專用的protoc的生成器 ```shell go get github.com/golang/protobuf/protoc-gen-go ``` 安裝後會在`GOPATH`目錄下生成可執行檔案,protobuf的編譯器外掛`protoc-gen-go`,等下執行`protoc`命令會自動呼叫這個外掛 - **第四步**: 安裝go-micro對應的外掛 ```shell go get github.com/micro/protoc-gen-micro ``` ## 2. 改造之前的client ### 2.1 新建proto檔案 - 新建`models/protos`資料夾 - 在上述資料夾下新建`prod.proto`檔案,內容如下: ``` syntax = "proto3"; package Models; message ProdModel { int32 Id = 1; string Name = 2; } message ProdRequest { int32 Size = 1; } message ProdListResponse{ repeated ProdModel data = 1; } ``` ### 2.2 執行protoc命令生成go檔案 在`models/protos`資料夾下執行以下命令 ``` protoc --micro_out=../ --go_out=../ prods.proto ``` ### 2.3 然後把原來的map修改成具體的型別就可以了 ```go package main import ( "context" "fmt" "gomicro-quickstart/goplugin_http_proto_invoker/models" "log" "github.com/micro/go-micro/client" "github.com/micro/go-micro/client/selector" "github.com/micro/go-micro/registry" "github.com/micro/go-plugins/client/http" "github.com/micro/go-plugins/registry/consul" ) func main() { // 1. 註冊consul地址 cr := consul.NewRegistry(registry.Addrs("47.100.220.174:8500")) // 2. 例項化selector mySelector := selector.NewSelector( selector.Registry(cr), // 傳入上面的consul selector.SetStrategy(selector.RoundRobin), // 指定獲取例項的演算法 ) // 3. 請求服務 resp, err := callByGoPlugin(mySelector) if err != nil { log.Fatal("request API failed", err) } fmt.Printf("[服務呼叫結果]:\r\n %v", resp) } func callByGoPlugin(s selector.Selector) ([]*models.ProdModel, error) { // 1. 呼叫`go-plugins/client/http`包的函式獲取它們提供的httpClient gopluginClient := http.NewClient( client.Selector(s), // 傳入上面的selector client.ContentType("application/json"), // 指定contentType ) // 2. 新建請求物件,傳入: (1)服務名 (2)endpoint (3)請求引數 req := gopluginClient.NewRequest("ProductService", "/v1/list", models.ProdRequest{Size: 2}) // 3. 新建響應物件,並call請求,獲取響應 var resp models.ProdListResponse err := gopluginClient.Call(context.Background(), req, &resp) if err != nil { return nil, err } return resp.GetData(), nil } ``` ## 3. 處理json tag不一致的問題 如果服務端的model設定了json tag,如下 ![](https://tva1.sinaimg.cn/large/007S8ZIlgy1gi5ric9ixzj30iv0bsdgw.jpg) 只有將客戶端的proto檔案生成的`pb.go`檔案中的model的tag修改成一樣的才可以 這裡可以使用外掛修改 **第一步:下載外掛** ```shell go get -u github.com/favadi/protoc-go-inject-tag ``` **第二步,在proto檔案上加註釋** ``` syntax = "proto3"; package models; message ProdModel { // @inject_tag: json:"pid" int32 Id = 1; // @inject_tag: json:"pname" string Name = 2; } message ProdRequest { int32 Size = 1; } message ProdListResponse{ repeated ProdModel data = 1; } ``` **第三步:使用命令列批量修改** ```shell protoc-go-inject-tag -input=../prods.pb