結構定義生命週期管理

隨著應用程式及其資料需求改變,Kafka 訊息的結構也需要調整。有效管理結構定義生命週期,是順利處理這些變更並維持資料完整性的關鍵。這個程序不僅涉及變更結構定義,還包括有系統地控管對應用程式而言安全或足夠相容的變更類型,這些應用程式會依附於結構定義。

Managed Service for Apache Kafka 結構定義登錄服務支援結構定義管理完整生命週期,並提供下列功能:

  • 定義及強制執行相容性規則 (相容性類型),以便在導入新的結構定義版本時,管理結構定義演變。這些規則可確保生產者和消費者繼續正常運作。

  • 設定作業控制項 (結構定義模式),管理不同層級的結構定義可變動性,保護資料處理管道。

  • 管理結構定義參照,在結構定義中提高重複使用率並維持一致性。

結構定義更新作業的運作方式

  1. 修改結構定義。舉例來說,在 .proto.avsc 檔案中新增選填欄位。

  2. 使用新結構定義設定的製作人傳送訊息,或您明確嘗試使用 API 或用戶端程式庫註冊新結構定義。auto.register.schemas=true

  3. 當新版本的註冊要求送達結構定義儲存庫時,系統會擷取目標主體設定的相容性規則。並根據該規則,比較建議的新結構定義與先前必要版本。

  4. 如果結構定義版本相容,系統會將新結構定義註冊為該主體下的下一個版本,並指派新的版本編號,如果定義是唯一的,也可能會指派新的 schema_id

  5. 生產者 (如適用) 會收到 schema_id,並將其納入訊息中。

  6. 如果結構定義版本不相容,註冊嘗試就會失敗,並傳回錯誤。

關於相容性類型

您可以透過結構定義相容性,定義結構定義儲存庫如何處理不同結構定義版本之間的相容性檢查。您可以在結構定義登錄檔階層結構中的各個層級套用這些設定,如下列資源模式選項所示:

  • 登錄檔層級:為整個結構定義登錄檔設定預設設定。

    • 路徑: projects/project/locations/location/schemaRegistries/schema_registry/config
  • 預設背景資訊中的主體層級:為登錄檔預設背景資訊中的主體設定特定設定。

    • 路徑: projects/project/locations/location/schemaRegistries/schema_registry/config/subject
  • 特定背景資訊中的主體層級:為具名背景資訊中的主體設定特定設定。

    • 路徑: projects/project/locations/location/schemaRegistries/schema_registry/contexts/context/config/subject

主體層級的設定會覆寫登錄層級的設定。 如果未在主體層級指定設定,系統會沿用登錄層級的值。如果未在登錄層級明確設定,預設值為 Backward

結構定義儲存庫會根據下列可用類型,比較新舊結構定義版本:

  • None不會執行相容性檢查。允許任何變更,但用戶端中斷的風險很高。

  • Backward (預設):使用新結構定義的消費者應用程式,只能解碼先前註冊的結構定義所產生的資料。可新增選填欄位和刪除欄位。消費者必須先升級,才能升級製作人。

  • Backward_transitive使用新結構定義的消費者應用程式可以解碼所有先前版本結構定義產生的資料。這項設定比 Backward 更嚴格。

  • Forward使用新結構定義產生的資料,必須可供使用先前註冊結構定義的用戶端讀取。生產者必須先升級,但使用新結構定義的消費者可能無法讀取以更舊結構定義產生的資料。這項設定可讓您刪除選填欄位及新增欄位。

  • Forward_transitive使用新結構定義產生的資料,必須可透過所有先前的結構定義版本讀取。這項設定比 Forward 更嚴格。

  • Full新結構定義可與先前註冊的結構定義版本回溯及前向相容。用戶端可以按照相對於生產者的任何順序,使用新結構定義升級。可新增或刪除選填欄位。

  • Full_transitive新結構定義可與該主題中的所有先前結構定義版本回溯及前向相容。這項設定比 Full 嚴格。

相容性類型範例

假設您有一個結構定義儲存庫,相容性類型為 Backward。您也可以在這個登錄檔中建立多個主體,這些主體會沿用登錄檔的Backward相容性。

如果特定主體命名為 user-events,則需要更嚴格的相容性規則。將 user-events 主體的結構定義相容性層級更新為 Full

在這種情況下,請遵守下列規則:

  • user-events 主體下註冊的任何新結構定義版本,都必須與該主體先前註冊的結構定義版本回溯相容和前向相容。

  • 除非已明確設定相容性,否則結構定義儲存庫中的其他主體仍會遵循儲存庫層級的 Backward 相容性設定。

如果日後將結構定義儲存庫的相容性層級變更為 Forward,這項變更會影響在儲存庫中建立的主體的預設相容性。不過,user-events 主體會保留明確設定的 Full 相容性,因為主體層級的設定會覆寫登錄層級的設定。

這項範例說明如何為整個登錄檔設定預設相容性層級,同時根據應用程式需求,彈性地為個別主體定義特定相容性規定。

詳情請參閱「更新相容性類型」。

相容性模式最佳做法

  • 請勿使用 None 做為相容性類型策略,因為這樣可能會因結構定義變更而導致用戶端中斷。

  • 如要優先更新製作人,請選擇以轉送為主的策略,例如 ForwardForward-transitive。如要優先更新消費者,請選擇以向後相容為主的策略,例如 BackwardBackward-transitive

  • 如要維持與多個先前結構定義版本的相容性,請選擇遞移策略。如要盡量提高相容性,並在更新結構定義版本時盡量降低用戶端中斷的風險,請使用 Full-transitive 策略。

關於結構定義參照

您可以使用結構定義參照,定義一次通用結構,並從多個結構定義參照這些結構。舉例來說,Address 結構定義可用於 CustomerSupplier 結構定義。

這個方法可提高架構的重複使用率和一致性。此外,使用結構定義參照可建立明確的依附元件,明確追蹤哪些結構定義依附於其他結構定義。這有助於提升架構架構的可維護性。

如果某個結構定義需要使用另一個通用結構定義,則會包含對該通用結構定義的參照。這種關係由 SchemaReference 結構正式定義。

SchemaReference 包含下列元件:

  • name (字串):Avro 格式所參照的結構定義完整名稱,或是 Protobuf 格式的匯入型別檔案名稱,如結構定義本身所用。

  • subject (字串):結構定義儲存庫中註冊參照結構定義的主體名稱。

  • version (int32):參照結構定義的特定版本號碼。

使用其他結構定義的結構定義會在 references 欄位中宣告這些依附元件。這個欄位會保留 SchemaReference 物件清單。

結構定義參照範例

假設您需要為 Customer 資料和 Supplier 資料定義結構定義,且兩者都必須包含地址。有了結構定義參照,您就能定義地址結構一次,然後重複使用。

如要按照這個範例操作,請參閱「建立主體」。

  1. 建立名為 address_schema 的主體,並註冊標準地址的定義。首次建立主體時,您也會建立該主體的結構定義第 1 版。

    Avro

    建立並儲存為受試者版本 1。address_schema_avro

    {
      "type": "record",
      "name": "Address",
      "namespace": "com.example.common",
      "fields": [
        {"name": "street", "type": "string"},
        {"name": "city", "type": "string"},
        {"name": "zipCode", "type": "string"},
        {"name": "country", "type": "string", "default": "USA"}
      ]
    }
    

    Protobuf

    建立並儲存為受試者版本 1。address_schema_proto

    syntax = "proto3";
    
    package com.example.common;
    
    message Address {
      string street = 1;
      string city = 2;
      string zip_code = 3;
      string country = 4;
    }
    
  2. 建立 customer_schema 結構定義。您會參照 address_schema 架構,而不是重複地址欄位。

    Avro

    billingAddress 欄位的 com.example.common.Address 類型是指上一步定義的 Address 結構定義。

    {
      "type": "record",
      "name": "Customer",
      "namespace": "com.example.crm",
      "fields": [
        {"name": "customerId", "type": "long"},
        {"name": "customerName", "type": "string"},
        // This field's type refers to the Address schema
        {"name": "billingAddress", "type": "com.example.common.Address"}
      ]
    }
    

    註冊 customer_schema_avro 時,中繼資料會包含結構定義參照:

    // Conceptual metadata for customer_schema_avro
    "references": [
      {
        "name": "com.example.common.Address",
        "subject": "address_schema_avro",
        "version": 1
      }
    ]
    

    Protobuf

    customer.proto 檔案會匯入 address.proto,並將 com.example.common.Address 用於 billing_address 欄位。

    syntax = "proto3";
    package com.example.crm;
    import "address.proto";
    
    message Customer {
      int64 customer_id = 1;
      string customer_name = 2;
      // This field's type refers to the imported Address message
      com.example.common.Address billing_address = 3;
    }
    

    註冊 customer_schema_proto 時,中繼資料會包含結構定義參照:

    // Conceptual metadata for customer_schema_proto
    "references": [
      {
        "name": "address.proto",
        "subject": "address_schema_proto",
        "version": 1
      }
    ]
    
  3. 同樣地,對於 Supplier 結構定義,您會新增指向相同通用 Address 結構定義的結構定義參照。

關於結構定義模式

結構定義模式會定義結構定義儲存庫或特定主體的運作狀態,並控管允許的修改類型。結構定義模式可以套用至登錄檔,或結構定義登錄檔中的特定主體。以下是結構定義模式資源的路徑:

  • 登錄層級模式:適用於整個結構定義登錄。

    • 路徑: projects/project/locations/location/schemaRegistry/schema_registry/mode
  • 登錄層級主體模式:適用於整個結構定義登錄中的特定主體。

    • 路徑: projects/project/locations/location/schemaRegistries/schema_registry/mode/subject

支援的模式如下:

  • Readonly:在此模式下,您無法更新結構定義登錄或指定的主體。您無法進行修改,例如更新設定或新增結構定義版本。

  • Readwrite:這個模式允許對結構定義登錄或指定主體執行有限的寫入作業。可進行修改,例如更新設定及新增結構定義版本。新結構定義儲存庫和新主體都會預設採用這個模式。

判斷是否允許修改特定主體時,系統會優先採用主體層級的模式,而非結構定義儲存庫層級的模式。

舉例來說,如果結構定義登錄檔處於 Readonly 模式,但其中的特定主體處於 Readwrite 模式,則允許修改該特定主體。不過,建立新主體時會受到登錄層級 Readonly 模式的限制。

結構定義模式範例

假設結構定義儲存庫的模式設為 Readwrite。這項設定表示您可以將新主體新增至登錄檔,並將新結構定義版本新增至現有主體。

假設您有名為 production-config 的主體,想要避免意外變更。您將 production-config 主體的模式設為 Readonly。因此,production-config 主題適用下列條件:

  • 您無法將新的結構定義版本新增至主體。

  • 您無法更新主體的設定 (例如相容性類型)。

  • 如果登錄檔中的其他主體未明確設定自己的模式,則會維持 Readwrite 模式,因此您仍可修改這些主體。

  • 您仍可在登錄檔中建立主體,因為登錄檔本身仍處於 Readwrite 模式。

之後,您可能會決定將整個結構定義儲存庫設為維護狀態,方法是將儲存庫層級模式設為 Readonly。不過,您還有另一個主體 staging-config,需要保持可修改狀態,以利持續進行測試。您明確將 staging-config 主體的模式設為 Readwrite。因此,staging-config主體須符合下列條件:

  • 結構定義儲存庫現在是 Readonly。你無法建立新科目。

  • 大多數現有主題 (例如沒有特定模式覆寫的主題) 也會透過繼承成為 Readonly。您無法為這些項目新增結構定義版本,也無法更新設定。

  • production-config 主體會維持明確設定的 Readonly

  • staging-config 主體仍處於 Readwrite 模式,因為主體層級設定會覆寫登錄層級的 Readonly 模式。您可以繼續新增結構定義版本,並更新 staging-config 的設定。

這種階層式做法可彈性管理不同精細程度的結構定義修改。

如要進一步瞭解如何更新結構定義模式,請參閱「更新結構定義模式」。

建議在正式環境中使用的結構定義登錄設定

如要在正式環境中保護結構定義,請套用下列設定:

  • 為整個結構定義儲存庫或特定生產主題設定 mode=READONLY,防止註冊新結構定義。

  • 請確保 Kafka 用戶端沒有 create version 權限,防止建立新的結構定義版本。

  • 在 Kafka 用戶端序列化程式中,設定 auto.register.schemas=false。如果是 Kafka Connect,請視需要為鍵和值序列化程式設定這項設定:

    • key.serializer.auto.register.schemas=false
    • value.serializer.auto.register.schemas=false
  • (選用) 如要強制用戶端使用主體的最新結構定義,請在序列化程式或還原序列化程式中設定 use.latest.version=true。這項設定會指示用戶端使用為主體註冊的最新結構定義版本,而非與特定訊息相符的版本。

後續步驟

Apache Kafka® 是 The Apache Software Foundation 或其關聯企業在美國與/或其他國家/地區的註冊商標。