聊一聊和Nacos 2.0.0對接那些事

前言

nacos 2.0.0 已經發布了 alpha1, alpha2 和 beta 三個版本了,部分測試報告也已經出來了。

還是比較值得期待的。

前段時間也一直在完善 nacos-sdk-csharp 這個項目。

主要就是對接 Nacos 2.0.0 這一塊,也考慮到之前主要是針對Open API封裝,同時參考JAVA的SDK進行功能疊加。

這一次就索性全部重新來過了,也對齊 JAVA SDK 提供的方法。

這其中最爲重要的應該是底層協議由 HTTP 換成 gRPC,也是長輪詢到長連接的一個跨越。

現在就和大家簡單梳理一下老黃在對接中認爲要注意的地方。

這裏以 nacos 2.0.0 beta 版本爲準,後續版本可能會有變化。

端口

nacos 的默認端口是 8848,也是之前 HTTP 協議對接時的請求端口,那麼我們是不是通過 8848 這個端口進行 gRPC 的交互呢?

答案是否定的!

nacos 裏面做了一個約定,把 gRPC 的服務端口設置成 nacos 啓動的端口加 1000。

也就是說,nacos 的端口是 8848 的話,那麼 gRPC 服務端口就是 9848

所以這裏是第一個注意的點。

proto 文件

下面是 nacos 提供的 proto 文件,這個是SDK和Server交互的基礎。

syntax = "proto3";

import "google/protobuf/any.proto";
import "google/protobuf/timestamp.proto";

option java_multiple_files = true;
option java_package = "com.alibaba.nacos.api.grpc.auto";

message Metadata {
    string type = 3;
    map<string, string> headers = 7;
}

message Payload {
    Metadata metadata = 2;
    google.protobuf.Any body = 3;
}

service RequestStream {
    // build a streamRequest
    rpc requestStream (Payload) returns (stream Payload) {
    }
}

service Request {
    // Sends a commonRequest
    rpc request (Payload) returns (Payload) {
    }
}

service BiRequestStream {
    // Sends a commonRequest
    rpc requestBiStream (stream Payload) returns (stream Payload) {
    }
}

這裏有 3 個 service,其中 RequestStream 這個在實際對接中是沒有使用到的。 所以只介紹其他兩個。

Request 這個是通用請求,發佈配置,註冊服務之類的請求都是通過這個方法來交互的。

BiRequestStream 這個是雙向流,主要是用來註冊連接,和一些監聽回調。

Nacos 1.x 裏面, 配置的監聽回調是基於長輪詢機制,服務的監聽回調是基於udp機制。

再來看看 service 的參數和響應。

Payload 的設計是有兩個部分, 一個是自定義類型的 metadata, 一個是 Any 類型的 body

metadata 裏面有一個 type 字段,這個字段代表的是客戶端和服務端交互的 RPC 語義。好比說,我要發佈配置,就是通過這個 type 告訴服務端,當前請求是要做什麼。

body 這個在交互時需要做一下轉換,拿到一個 object 對象,序列化成一個 JSON 字符串,最後在轉化成 Any 類型的 value。

下面是一個簡單的示例:

var body = new Google.Protobuf.WellKnownTypes.Any
{
    // convert the request paramter to a json string, as the body
    Value = Google.Protobuf.ByteString.CopyFromUtf8(request.ToJsonString())
};

這裏有一個要注意的地方,在生成 C# 代碼後,會因爲參數名和方法名一樣造成編譯不過,所以這裏要修改一下生成代碼的參數名。

對接

知道了服務端的端口, proto 文件也有了,接下來就可以和服務端對接了。

想要和服務端對接上,成功獲取到正確的數據,其實還有不少內容的。

下面老黃拆成 3 個小節來說。

建立連接

Step 1:

與 gRPC 服務端進行交互,首先就是要創建一個 Channel ,這裏用的是 Insecure 的方式,不需要提供額外的證書信息。

Step 2:

創建 Request 請求客戶端,併發起 ServerCheckRequest 請求,檢查服務是否可用,不可用就直接關閉這個 Channel 了。

Step 3:

創建 BiRequestStream 請求客戶端,註冊處理服務端推送的相關操作,主要是配置和服務的變更。

註冊完成後,還要發送 ConnectionSetupRequest 請求和 server 端建立真正意義上的連接。

這一步至關重要,因爲這一步過後,服務端會把這個連接維護到客戶端的連接管理裏面,後續的請求會通過這個來判斷是不是合法的請求。可以理解成拿到了大門的鑰匙。

這一步完成之後,就可以通過 Request 發送請求了。

請求與響應

這裏的請求,指的是通過 Request 發起的。

前面有提到,body 參數這一塊,是對一個 JSON 字符串進行轉化後的值。

這個 JSON 字符串大概成下面這樣。

{
    "headers": {
        "h1": "v1",
        "h2": "v2"
    },
    "requestId": "xxxx",
    "biz-prop-1": "value-1",
    "biz-prop-2": "value-2",
    "biz-prop-n": "value-n",
}

其中, headers 和 requestId 這兩個是通用參數,每個接口都應該帶上,其他的就是各個接口需要什麼就加什麼。

響應的話會有正常和異常。

正常的話,返回的 type 是和請求的 type 相對應的。

好比 ConfigPublishRequest 就會對應 ConfigPublishResponse

如果服務端處理異常了,就會返 ErrorResponse

這裏的異常可以分爲兩類。

  1. 請求沒有註冊
{"resultCode":500,"errorCode":301,"message":"Connection is unregistered.","success":false} 

出現這種情況後,客戶端這邊是要重新和服務端進行連接,不然所有的請求都會是這個返回。

可能的原因有:

  • 在請求之前沒有提前在雙向流裏面發起建立連接的請求。
  • 客戶端與服務端斷開過連接
  1. 請求處理失敗

這個一般就是服務端處理出現了異常。

重新連接

如果響應告訴客戶端請求沒有註冊,這個時候要及時觸發重新連接,這樣纔不會讓業務受到影響。

觸發重連操作後,會有一個 SwitchServer 的操作,可以簡單理解成換了一個服務地址,然後重複連接裏面的幾個步驟。

到這裏其實對接相關的內容基本差不多了,剩下的就是對接具體的請求和其他操作了。

也附上一張老黃之前畫的粗糙的圖。

寫在最後

老黃參與的 nacos-sdk-csharp 目前已經基本適配好了 nacos 2.0.0 beta 版本,但是還有許多細節需要慢慢的調整和改進。

希望有感興趣的大佬一起參與到這個項目來。

nacos-sdk-csharp 的地址 :https://github.com/nacos-group/nacos-sdk-csharp

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章