共用方式為


訊息複寫工作模式

同盟概觀複寫器函數概觀說明複寫工作的原理和基本元素,建議您先熟悉這些項目再繼續閱讀本文。

在本文中,我們會詳細指導如何實作概觀一節中所強調的幾個模式。

複寫

複寫模式會將訊息從某個佇列或主題複製到下一個佇列或主題,或是從佇列或主題複製到其他目的地 (例如 事件中樞)。 系統會轉送這些訊息,而不會對訊息承載進行任何修改。

與 Azure 服務匯流排之間的訊息複寫範例中涵蓋了此模式的實作。

序列和順序保留

複寫模型的目的並非將來源佇列或主題的訊息絕對順序保留到目標佇列或主題中,而是著重於在必要時保留應用程式所需訊息的相對順序。 應用程式會啟用來源實體的工作階段支援,並將具有相同工作階段金鑰的相關訊息分組,從而實現目標。

透過工作階段感知的預建複寫函數,可確保從來源實體所擷取具有相同工作階段識別碼的訊息序列,能夠根據原始序列和相同工作階段識別碼整批提交至目標佇列或主題。

服務指派的中繼資料

從來源佇列或主題所取得訊息的服務指派中繼資料、原始的加入佇列時間和序號,都會由目標佇列或主題內新的服務指派值取代,但使用範例所提供的預設複寫工作,原始值則保留在使用者屬性中:repl-enqueue-time (ISO8601 字串) 和 repl-sequence

這些屬性的類型為字串,而且包含各自原始屬性的 stringified 值。 如果訊息經多次轉送,則服務指派給直接來源的中繼資料會附加至任何已存在的屬性,而且值以分號隔開。

容錯移轉

如果使用複寫進行災害復原,以防止服務匯流排服務發生區域可用性訊息或網路中斷,任何這類失敗案例都需要從原來的佇列或主題容錯移轉到下一個佇列或主題,並告知生產者和/或取用者使用次要端點。

在所有容錯移轉案例中,會假設命名空間的必要元素結構都相同,這表示佇列和主題的名稱相同,而且會以相同方式設定共用存取簽章規則和/或角色型存取控制規則。 依照移動命名空間的指引操作,並省略清除步驟,即可建立 (並更新) 次要命名空間。

若要強制生產者和取用者切換,您必須將要使用哪個命名空間的資訊放在容易存取及更新的位置以供查閱。 如果生產者或取用者遇到頻繁或持續性的錯誤,則應查閱該位置並調整其設定。 共用該設定的方式有許多種,以下點出其中兩個方法:DNS 和檔案共用。

以 DNS 為基礎的容錯移轉設定

其中一個候選方法是在受您控制的 DNS 內保存 DNS SRV 記錄中的資訊,並指向各自的佇列或主題端點。 請注意,訊息中樞不允許其端點直接以 CNAME 記錄為別名,這表示您需使用 DNS 做為端點位址的復原性查閱機制,而不是直接解析 IP 位址資訊。

假設您擁有網域 example.com,以及用於應用程式的區域 test.example.com。 針對兩個替代服務匯流排,您現在需建立兩個額外的巢狀區域,以及為各個區域建立一筆 SRV 記錄。

SRV 記錄遵循一般慣例,首碼為 _azure_servicebus._amqp 並保留兩個端點記錄:一個用於連接埠 5671 上透過 TLS 傳送的 AMQP,另一個用於連接埠 443 上透過 WebSocket 傳送的 AMQP,兩者都會指向對應至該區域命名空間的服務匯流排端點。

區域 SRV 記錄
sb1.test.example.com _azure_servicebus._amqp.sb1.test.example.com
1 1 5671 sb1-test-example-com.servicebus.windows.net
2 2 443 sb1-test-example-com.servicebus.windows.net
sb2.test.example.com _azure_servicebus._amqp.sb1.test.example.com
1 1 5671 sb2-test-example-com.servicebus.windows.net
2 2 443 sb2-test-example-com.servicebus.windows.net

在應用程式的區域中,您須建立一個 CNAME 項目,指向對應至主要佇列或主題的從屬區域:

CNAME 記錄 Alias
servicebus.test.example.com sb1.test.example.com

使用明確允許查詢 CNAME 和 SRV 記錄的 DNS 用戶端 (JAVA 和 .NET 的內建用戶端只允許對 IP 位址的名稱進行簡單解析),您就可以解析所需的端點。 例如使用 DnsClient.NET 時,lookup 函數為:

static string GetServiceBusName(string aliasName)
{
    const string SrvRecordPrefix = "_azure_servicebus._amqp.";
    LookupClient lookup = new LookupClient();

    return (from CNameRecord alias in (lookup.Query(aliasName, QueryType.CNAME).Answers)
            from SrvRecord srv in lookup.Query(SrvRecordPrefix + alias.CanonicalName, QueryType.SRV).Answers
            where srv.Port == 5671
            select srv.Target).FirstOrDefault()?.Value.TrimEnd('.');
}

此函數會傳回目前以 CNAME 為別名之區域的連接埠 5671 所註冊的目標主機名稱,如上所示。

執行容錯移轉需要編輯 CNAME 記錄,並將其指向替代區域。

使用 DNS (尤其是 Azure DNS) 的優點是,系統會全域複寫 Azure DNS 資訊,因此可在單一區域服務中斷時復原。

此程序類似服務匯流排異地複寫災害復原的運作方式,不過您擁有完整控制權,而且也適用於主動/主動案例。

以檔案共用為基礎的容錯移轉設定

使用 DNS 來共用端點資訊最簡單的替代方式,就是將主要端點的名稱放入純文字檔案中,並從可有效防止服務中斷且仍允許更新的基礎結構提供該檔案。

如果您已經透過全球可用性和內容複寫來執行高可用性的網站基礎結構,請在該處新增這類檔案,並在需要切換時重新發佈檔案。

合併

合併模式有一或多個複寫工作指向一個目標,一般產生者可能也同時將訊息傳送至相同的目標。

此模式的變化如下:

  • 兩個或多個複寫函數同時從不同的來源取得訊息,並將訊息傳送至相同的目標。
  • 另一個複寫函數從某個來源取得訊息,而生產者也同時直接使用目標。
  • 第一個模式,不過訊息會在兩個或多個主題之間進行鏡像處理,無論訊息在哪裡產生,都會導致這些主題包含相同的訊息。

前兩個模式的變化很簡單,而且與一般複寫工作並無不同。

最後一個情況則需排除已複寫的訊息,避免再次複寫。 主動/主動範例會示範並說明這項技巧。

編輯器

編輯器模式是以複寫模式為基礎,但會先修改訊息再加以轉送。 這類修改的範例如下:

  • 轉碼 - 如果訊息內容 (也稱為「主體」或「承載」) 是來自使用 Apache Avro 格式或某些專屬序列化格式進行編碼的來源,但是擁有目標的系統預期內容是以 JSON 編碼,轉碼複寫工作會先將 Apache Avro 的承載還原序列化為記憶體內物件圖形,然後再為轉送中的訊息將該圖形序列化成 JSON 格式。 轉碼也包含內容壓縮和解壓縮工作。
  • 轉換 - 包含結構化資料的訊息可能需要重新整理這些資料,以方便下游取用者取用。 這個過程可能包含壓平合併巢狀結構、剪除沒有直接關聯的資料元素,或將裝載重新整理為完全符合指定的結構描述。
  • 批次處理 - 來自一個來源的訊息能以批次方式接收 (單次傳輸多個訊息),但必須單獨轉送到目標,反之亦然。 因此,一個工作可根據單一輸入訊息傳輸來轉送多個訊息,也可彙總一組訊息再一起傳輸。
  • 驗證 - 若訊息資料來自外部來源,通常需要先檢查是否符合一組規則,才可加以轉送。 這些規則可以使用結構描述或程式碼來表示。 不合規的訊息可能會遭捨棄並在記錄中註明問題,或可能會轉送到特殊目標目的地,以待進一步處理。
  • 擴充 - 來自某些來源的訊息資料可能需要提供進一步內容加以擴充,才能在目標系統中使用。 這個過程可能包含查閱參考資料,並透過訊息內嵌這些資料,或新增複寫工作已知但不包含在訊息中的來源相關資訊。
  • 篩選 - 可能必須根據某些規則從目標中清除來自某個來源的部分訊息。 篩選條件會根據規則來測試訊息,並在訊息不符合規則時卸除訊息。 篩選的形式為觀察特定條件並卸除具有相同值的後續訊息,藉此篩選掉重複的訊息。
  • 路由和資料分割 - 某些複寫工作可能允許兩個或多個替代目標,並根據訊息的中繼資料或內容,定義針對任何特定訊息選擇複寫目標的規則。 資料分割是一種特殊形式的路由,其中工作會根據規則明確指派一個複寫目標中的分割區。
  • 加密 - 複寫工作可能必須解密來自來源的內容,以及/或加密轉送至目標的內容,且/或可能必須驗證內容和中繼資料的完整性 (相對於訊息中所附的簽章),或附加這類簽章。
  • 證明 - 複寫工作可將中繼資料 (可能受數位簽章保護) 附加至證明訊息已透過特定通道或於特定時間接收的訊息。
  • 鏈結 - 複寫工作可將簽章套用至訊息的序列,讓序列的完整性受到保護,而且可以偵測到遺失的訊息。

您可以使用 Azure Functions 實作所有這些模式,透過訊息中樞觸發程序來取得訊息及透過佇列或主題輸出繫結來傳遞訊息。

路由

路由模式是以複寫模式為基礎,但不是具有一個來源和一個目標,而是複寫作業具有多個目標,底下以 C# 說明:

[FunctionName("SBRouter")]
public static async Task Run(
    [ServiceBusTrigger("source", Connection = "serviceBusConnectionAppSetting")] ServiceBusReceivedMessage[] messages,
    [ServiceBusOutput("dest1", Connection = "serviceBusConnectionAppSetting")] IAsyncCollector<dynamic> output1,
    [ServiceBusOutput("dest2", Connection = "serviceBusConnectionAppSetting")] IAsyncCollector<dynamic> output2,
    ILogger log)
{
    foreach (Message messageData in messages)
    {
        // send to output1 or output2 based on criteria 
    }
}

路由函數會考慮訊息中繼資料和/或訊息承載,然後挑選其中一個可用目的地來傳送。

下一步