使用 dubbogo-cli 工具

1. 安裝

dubbogo-cli 是 Apache/dubbo-go 生態系統的子項目,它為開發人員提供了便捷的功能,例如應用程式範本建立、工具安裝和介面除錯,以提高使用者研發效率。

執行以下指令將 dubbogo-cli 安裝到 $GOPATH/bin

go install github.com/dubbogo/dubbogo-cli@latest

2. 功能概述

dubbogo-cli 支援以下功能

  • 應用程式範本建立

    dubbogo-cli newApp.
    

    在目前目錄中建立應用程式範本

  • Demo 建立

    dubbogo-cli newDemo.
    

    在目前目錄中建立一個 RPC 範例,包含客戶端和伺服器端

  • 編譯和除錯工具安裝

    dubbogo-cli install all
    

    一鍵安裝以下工具到 $GOPATH/bin

    -protoc-gen-go-triple

    Compilation for triple protocol interface
    
  • 檢視 dubbo-go 應用程式註冊資訊

    • 檢視 Zookeeper 上的註冊資訊以取得介面和方法列表

      $ dubbogo-cli show --r zookeeper --h 127.0.0.1:2181
      interface: com.dubbogo.pixiu.UserService
      methods: [CreateUser, GetUserByCode, GetUserByName, GetUserByNameAndAge, GetUserTimeout, UpdateUser, UpdateUserByName]
      
    • 檢視 Nacos 上的註冊資訊 [功能開發中]

    • 檢視 Istio 的註冊資訊 [功能開發中]

  • 除錯 Dubbo 協定介面

  • 除錯 Triple 協定介面

3. 功能細節

3.1 Demo 應用程式介紹

3.1.1 Demo 建立

dubbogo-cli newDemo.

在目前目錄中建立一個 demo,包含客戶端和伺服器。該 demo 展示了基於一組介面完成 RPC 呼叫。

此 Demo 使用直連模式,不依賴註冊中心。服務端將服務暴露在本地 20000 端口,客戶端發起調用。

.
├── api
│ ├── samples_api.pb.go
│ ├── samples_api.proto
│ └── samples_api_triple.pb.go
├── go-client
│ ├── cmd
│ │ └── client.go
│ └── conf
│ └── dubbogo.yaml
├── go-server
│ ├── cmd
│ │ └── server.go
│ └── conf
│ └── dubbogo.yaml
└── go.mod

3.1.2 執行 Demo

啟動服務端

$ cd go-server/cmd
$ go run .

另一個終端開啟客戶端

$ go mod tidy
$ cd go-client/cmd
$ go run .

可以看到打印日誌

INFO cmd/client.go:49 client response result: name:"Hello laurence" id:"12345" age:21

3.2 應用模板介紹

3.2.1 應用模板創建

dubbogo-cli newApp.

在目前目錄中建立應用程式範本

.
├── Makefile
├── api
│ ├── api.pb.go
│ ├── api.proto
│ └── api_triple.pb.go
├──build
│ └── Dockerfile
├── chart
│ ├── app
│ │ ├── Chart.yaml
│ │ ├── templates
│ │ │ ├── _helpers.tpl
│ │ │ ├── deployment.yaml
│ │ │ ├── service.yaml
│ │ │ └── serviceaccount.yaml
│ │ └── values.yaml
│ └── nacos_env
│ ├── Chart.yaml
│ ├── templates
│ │ ├── _helpers.tpl
│ │ ├── deployment.yaml
│ │ └── service.yaml
│ └── values.yaml
├── cmd
│ └── app.go
├── conf
│ └── dubbogo.yaml
├── go.mod
├── go.sum
└── pkg
    └── service
        └── service.go

3.2.2 應用模板介紹

生成的專案包含幾個目錄

  • api:放置介面檔案:proto 檔案和生成的 .pb.go 檔案

  • build:放置鏡像構建相關檔案

  • Chart:放置用於發佈的 chart 倉庫,基礎環境 chart 倉庫:nacos、mesh(開發中)

  • cmd:程式入口

  • conf:框架配置

  • pkg/service:RPC 服務實現

  • Makefile

    • 鏡像、helm 部署名稱
      • IMAGE = $(your_repo)/$(namespace)/$(image_name) TAG = 1.0.0
  • HELM_INSTALL_NAME = dubbo-go-app,helm 安裝名稱,用於 helm install/uninstall 命令。

    • 提供如下腳本
      • make build # 打包鏡像並推送
  • make buildx-publish # arm 架構本地打包 amd64 鏡像並推送,依賴 docker buildx

  • make deploy # 通過 helm 發佈應用

  • make remove # 刪除已發佈的 helm 應用

  • make proto-gen # 生成 api 下的 pb.go 檔案

使用應用模板的開發流程

依賴環境:make、go、helm、kubectl、docker

  1. 通過 dubbogo-cli 生成模板
  2. 修改 api/api.proto
  3. make proto-gen
  4. 開發介面
  5. 修改 makefile 中的 IMAGE 鏡像名稱和 HELM_INSTALL_NAME 發佈名稱
  6. 製作鏡像並推送
  7. 修改 chart/app/values 中與部署相關的 value 配置,重點關注 image 部分。
image:
  repository: $(your_repo)/$(namespace)/$(image_name)
  pullPolicy: Always
  tag: "1.0.0"
  1. make deploy,使用 helm 發佈應用。

3.3 使用 gRPC 協定除錯 dubbo-go 應用

3.3.1 簡介

grpc_cli 工具是 gRPC 生態系統用於除錯服務的工具,它可以在伺服器端開啟[反射服務](https://github.com/grpc/grpc/blob/master/doc/server-reflection.md)的前提下,取得服務的 proto 檔案、服務名稱、方法名稱、參數列表,並發起 gRPC 調用。

Triple 協定相容 gRPC 生態,預設開啟了 gRPC 反射服務,因此可以直接使用 grpc_cli 除錯 triple 服務。

3.3.2 安裝 grpc_cli

後續安裝將由 dubbogo-cli 完成,目前需要用戶手動安裝

參考 grpc_cli 文件

3.3.3 使用 grpc_cli 除錯 Triple 服務

  1. 查看 triple 服務的介面定義
$ grpc_cli ls localhost:20001 -l
filename: helloworld.proto
package: org.apache.dubbo.quickstart.samples;
service UserProvider {
  rpc SayHello(org.apache.dubbo.quickstart.samples.HelloRequest) returns (org.apache.dubbo.quickstart.samples.User) {}
  rpc SayHelloStream(stream org.apache.dubbo.quickstart.samples.HelloRequest) returns (stream org.apache.dubbo.quickstart.samples.User) {}
}
  1. 查看請求參數類型

例如,開發者想要測試上述 port 的 SayHello 方法,並嘗試取得 HelloRequest 的具體定義,則需要執行以下命令查看對應參數的定義。

$ grpc_cli type localhost:20001 org.apache.dubbo.quickstart.samples.HelloRequest
message HelloRequest {
  string name = 1 [json_name = "name"];
}
  1. 請求介面

了解請求參數的具體類型後,即可發起調用測試對應的服務。查看返回值是否符合預期。

$ grpc_cli call localhost:20001 SayHello "name: 'laurence'"
connecting to localhost:20001
name: "Hello Laurence"
id: "12345"
age: 21
Received trailing metadata from server:
accept-encoding: identity, gzip
adaptive-service.inflight : 0
adaptive-service. remaining : 50
grpc-accept-encoding : identity,deflate,gzip
Rpc succeeded with OK status

3.4 使用 Dubbo 協定除錯 dubbo-go 應用

3.4.1 開啟 Dubbo 服務端

範例:user.go

func (u *UserProvider) GetUser(ctx context.Context, userStruct *CallUserStruct) (*User, error) {
fmt.Printf("=========================\nreq:%#v\n", userStruct)
rsp := User{"A002", "Alex Stocks", 18, userStruct.SubInfo}
fmt.Printf("========================\nrsp:%#v\n", rsp)
return &rsp, nil
}

服務端開啟一個名為 GetUser 的服務,傳入一個 CallUserStruct 參數,返回一個 User 參數 CallUserStruct 參數定義

type CallUserStruct struct {
ID string
Male bool
SubInfo SubInfo // nested substructure
}
func (cs CallUserStruct) JavaClassName() string {
return "com.ikurento.user.CallUserStruct"
}

type SubInfo struct {
SubID string
SubMale bool
SubAge int
}

func (s SubInfo) JavaClassName() string {
return "com.ikurento.user.SubInfo"
}

User 結構定義

type User struct {
Id string
name string
Age int32
SubInfo SubInfo // Nest the above substructure SubInfo
}

func (u *User) JavaClassName() string {
return "com.ikurento.user.User"
}

啟動服務

cd server`
`source builddev.sh`
`go run.

3.4.2 定義請求體(適配序列化協定)

請求體定義為 json 檔案,約定的鍵值均為字串。鍵對應 Go 語言 struct 的欄位名稱,例如 “ID” 和 “Name”,值對應 “type@val”。其中 type 支援 string int bool time,val 以字串初始化。如果只填寫 type,則初始化為零值。約定每個 struct 都必須有一個 JavaClassName 欄位,必須與服務端嚴格對應。

請參閱 userCall.json

{
  "ID": "string@A000",
  "Male": "bool@true",
  "SubInfo": {
    "SubID": "string@A001",
    "SubMale": "bool@false",
    "SubAge": "int@18",
    "JavaClassName": "string@com.ikurento.user.SubInfo"
  },
  "JavaClassName": "string@com.ikurento.user.CallUserStruct"
}

userCall.json 定義了參數 CallUserStruct 和子結構 SubInfo 的結構,並賦予請求參數值。

同樣地,user.json 不需要賦予初始值作為返回值,但 JavaClassName 欄位必須與伺服器端嚴格對應。

{
  "ID": "string",
  "Name": "string",
  "Age": "int",
  "JavaClassName": "string@com.ikurento.user.User",
  "SubInfo": {
    "SubID": "string",
    "SubMale": "bool",
    "SubAge": "int",
    "JavaClassName": "string@com.ikurento.user.SubInfo"
  }
}

3.4.3 除錯埠

./dubbo-go-cli -h=localhost -p=20001 -proto=dubbo -i=com.ikurento.user.UserProvider -method=GetUser -sendObj="./userCall.json" -recvObj="./user .json"

列印結果

2020/10/26 20:47:45 Created pkg:
2020/10/26 20:47:45 &{ID:A000 Male:true SubInfo:0xc00006ea20 JavaClassName:com.ikurento.user.CallUserStruct}
2020/10/26 20:47:45 SubInfo:
2020/10/26 20:47:45 &{SubID:A001 SubMale:false SubAge:18 JavaClassName:com.ikurento.user.SubInfo}


2020/10/26 20:47:45 Created pkg:
2020/10/26 20:47:45 &{ID: Name: Age:0 JavaClassName:com.ikurento.user.User SubInfo:0xc00006ec90}
2020/10/26 20:47:45 SubInfo:
2020/10/26 20:47:45 &{SubID: SubMale:false SubAge:0 JavaClassName:com.ikurento.user.SubInfo}


2020/10/26 20:47:45 connected to localhost:20001!
2020/10/26 20:47:45 try calling interface: com.ikurento.user.UserProvider.GetUser
2020/10/26 20:47:45 with protocol: dubbo

2020/10/26 20:47:45 After 3ms , Got Rsp:
2020/10/26 20:47:45 &{ID:A002 Name:Alex Stocks Age:18 JavaClassName: SubInfo:0xc0001241b0}
2020/10/26 20:47:45 SubInfo:
2020/10/26 20:47:45 &{SubID:A001 SubMale:false SubAge:18 JavaClassName:}```

您可以看到詳細的請求主體賦值,以及返回的結果和耗時。支援巢狀結構。

列印伺服器端結果

=========================
req:&main.CallUserStruct{ID:"A000", Male:true, SubInfo:main.SubInfo{SubID:"A001", SubMale:false, SubAge:18}}
=========================

可以看出,已接收到來自 cli 的數據。


上次修改日期:2023 年 1 月 2 日:增強 Dubbogo 文件 (#1800) (71c8e722740)