開發與維運

服務網格GPRC協議多種編程語言實踐-1 GPRC協議示例的設計

1 通信模型

設計宗旨

  • 覆蓋gRPC的4種通信模型。
  • 方法名和參數名不引入任何業務因素,避免額外思考,專注技術本身。

方法定義

  • Unary RPC: talk
  • Server streaming RPC: talkOneAnswerMore
  • Client streaming RPC: talkMoreAnswerOne
  • Bidirectional streaming RPC: talkBidirectional

protobuf定義

service LandingService {
  //Unary RPC
  rpc talk (TalkRequest) returns (TalkResponse) {
  }
  //Server streaming RPC
  rpc talkOneAnswerMore (TalkRequest) returns (stream TalkResponse) {
  }
  //Client streaming RPC with random & sleep
  rpc talkMoreAnswerOne (stream TalkRequest) returns (TalkResponse) {
  }
  //Bidirectional streaming RPC
  rpc talkBidirectional (stream TalkRequest) returns (stream TalkResponse) {
  }
}

方法設計

  • 簡單的主線邏輯:服務端將請求參數中的data字段的值作為hello數組的下標,並將相應的值返回給客戶端。
  • 簡化請求和響應形式,避免使用多個類型來區分單複數:

    • 請求統一使用字符串,複數形式使用逗號分開。
    • 響應統一使用數組,單數時數組只包含一條結果。
  • 客戶端和服務端都傳遞編程語言信息,以{lang}值顯式展示流量管理的配置效果。

grpc_diagram.png

2 協議設計

設計宗旨

  • 請求參數足夠簡單,以方便調試,但要包含足夠的信息。
  • 響應參數的數據類型要儘可能覆蓋全面,以實現演示的目的。

請求協議

只使用字符串類型,包含請求hello數組的下標值和編程語言信息。

message TalkRequest {
  //language index
  string data = 1;
  //clientside language
  string meta = 2;
}

響應協議

  • 響應只包含兩個字段,整數類型的狀態碼和TalkResult類型的數組。
  • TalkResult類型內部,分別定義了長整型、枚舉類型、鍵值類型(k/v的泛型為字符串)。
message TalkResponse {
  int32 status = 1;
  repeated TalkResult results = 2;
}

message TalkResult {
  //timestamp
  int64 id = 1;
  //enum
  ResultType type = 2;
  // result uuid
  // language index
  // data hello
  // meta serverside language (It's not good here, 
  //      but ok since I feel like to keep the response)
  map<string, string> kv = 3;
}

enum ResultType {
  OK = 0;
  FAIL = 1;
}

3 實現要點

環境變量

我們需要為GRPC的client提供一個變量GRC_SERVER,在本地開發調試時其值為localhost,在POD啟動時動態定義為GRPC Service的值,以便client調用。

隨機數

在Client streaming和Bidirectional streaming兩種通信方式下,客戶端需要隨機產生一個整型數值,取值要求在hello數組下標的範圍內。

時間戳

TalkResult.idint64類型的唯一標識,通過時間戳來實現。

UUID

TalkResult.kv[id]是字符串類型的唯一標識,我們通過UUID來實現。

sleep

在streaming方式下,為了更好地觀察,通過sleep方式設置兩次請求的間隔。

Leave a Reply

Your email address will not be published. Required fields are marked *