在應用程式的多個執行個體之間平衡分割區負載

若要調整您的事件處理應用程式,您可以執行應用程式的多個執行個體,並在這些執行個體之間平衡負載。 在舊版和已淘汰的版本中,EventProcessorHost 可讓您在接收事件時,平衡程式多個執行個體與檢查點事件之間的負載。 在較新的版本中 (5.0 以後的版本),EventProcessorClient (.NET 和 Java) 或 EventHubConsumerClient (Python 和 JavaScript) 可讓您執行相同的作業。 使用事件可讓開發模型變得更簡單。 您可以註冊事件處理常式來訂閱您感興趣的事件。 如果您使用舊版的用戶端程式庫,請參閱下列移轉指南:.NETJavaPythonJavaScript

本文說明使用多個用戶端應用程式執行個體從事件中樞讀取事件的範例案例, 並提供事件處理器用戶端功能的詳細資料。事件處理器用戶端可讓您一次從多個分割區接收事件,並與使用相同事件中樞和取用者群組的其他取用者進行負載平衡。

注意

分割取用者概念是針對事件中樞調整大小的關鍵。 與競爭取用者模式相比,分割取用者模式可藉由消除爭奪瓶頸,以及加速端對端平行處理原則來具有高度縮放能力。

範例案例

針對範例案例,請設想有一家監視 100,000 戶家庭的住家安全公司。 每隔一分鐘,此公司就會從每個家庭中安裝的各種感應器取得資料,這些感應器包括動作偵測器、門窗開啟感應器、玻璃破壞偵測器等。 該公司會提供網站給住戶,讓他們可幾乎即時地監視房子內的動態。

每個感應器會將資料推送至事件中樞。 事件中樞已設定 16 個分割區。 在取用端,您需要一種機制來讀取這些事件、合併這些事件 (篩選、彙總等等),以及將彙總資料備份至儲存體 Blob,使其可接著投射至方便使用的網頁。

取用者應用程式

在分散式環境中設計取用者時,案例必須處理下列需求:

  1. 縮放:建立多個取用者,而每個取用者都會負責從幾個事件中樞分割區讀取資料。
  2. 負載平衡:以動態方式增加或減少取用者。 例如,對每個家庭新增感應器類型 (例如一氧化碳偵測器) 時,事件數目就會增加。 在此情況下,操作人員 (人類) 會增加取用者執行個體的數目。 然後,取用者集區可以重新平衡他們擁有的分割區數目,讓新增的取用者共同分攤負載。
  3. 在失敗時無縫接續:如果取用者 (取用者 A) 發生失敗 (例如,裝載取用者的虛擬機器突然損毀),則其他取用者可以接手取用者 A 負責的分割區並繼續作業。 此外,接續點 (稱為「檢查點」或「位移」) 應剛好位在取用者 A 失敗的位置,或在此稍微前面一點的位置。
  4. 取用事件:前面三個重點在處理取用者管理,但還必須有程式碼來取用事件並發揮這些事件的用處。 例如,彙總並上傳至 Blob 儲存體。

事件處理器或取用者用戶端

您不需要建置自己的解決方案來滿足這些需求。 Azure 事件中樞 SDK 提供此功能。 在 .NET 或 Java SDK 中,您使用事件處理器用戶端 (EventProcessorClient),而在 Python 和 JavaScript SDK 中,您使用 EventHubConsumerClient。 在舊版 SDK 中,主要靠事件處理器主機 (EventProcessorHost) 來支援上述功能。

在大多數的生產案例中,我們建議您使用事件處理器用戶端來讀取和處理事件。 處理器用戶端旨在提供健全的體驗,讓您以高效能且容錯的方式處理事件中樞所有分割區的事件,同時提供檢查其進度的方法。 事件處理器用戶端可以在指定事件中樞的取用者群組內容中以合作方式進行。 用戶端會隨著執行個體是否可供群組使用,自動管理工作的散發和平衡。

分割區的擁有權

事件處理器執行個體通常會擁有並處理來自一或多個分割區的事件。 分割區的擁有權會平均分散到與事件中樞和取用者群組組合相關聯的所有作用中事件處理器執行個體。

每個事件處理器都會獲得獨特的識別碼,並藉由新增或更新檢查點存放區中的項目來宣告分割區的擁有權。 所有事件處理器執行個體都會定期與此存放區進行通訊,以更新自己的處理狀態和了解其他作用中執行個體。 這項資料接著會用來平衡作用中處理器之間的負載。 新的執行個體可以加入處理集區來擴大規模。 當執行個體關閉時,無論是因為失敗或縮小,分割區擁有權都會正常地傳輸至其他作用中處理器。

檢查點存放區中的分割區擁有權記錄會追蹤事件中樞命名空間、事件中樞名稱、取用者群組、事件處理器識別碼 (也稱為擁有者)、分割區識別碼和上次修改時間。

事件中樞命名空間 事件中樞名稱 取用者群組 負責人 分割識別碼 上次修改時間
mynamespace.servicebus.windows.net myeventhub myconsumergroup 3be3f9d3-9d9e-4c50-9491-85ece8334ff6 0 2020-01-15T01:22:15
mynamespace.servicebus.windows.net myeventhub myconsumergroup f5cc5176-ce96-4bb4-bbaa-a0e3a9054ecf 1 2020-01-15T01:22:17
mynamespace.servicebus.windows.net myeventhub myconsumergroup 72b980e9-2efc-4ca7-ab1b-ffd7bece8472 2 2020-01-15T01:22:10
mynamespace.servicebus.windows.net myeventhub myconsumergroup 844bd8fb-1f3a-4580-984d-6324f9e208af 15 2020-01-15T01:22:00

每個事件處理器執行個體都會取得分割區的擁有權,並開始從最後已知檢查點處理分割區。 如果處理器失敗 (VM 關閉),則其他執行個體會藉由查看上次修改時間來進行偵測。 其他執行個體會嘗試取得先前由非作用中執行個體所擁有分割區的擁有權, 而檢查點存放區可保證只有其中一個執行個體會成功宣告分割區的擁有權。 因此,在任何指定的時間點,最多會有一個從分割區接收事件的處理器。

接收訊息

在建立事件處理器時,您要指定處理事件和錯誤的函式。 每次呼叫處理事件的函式都會從特定分割區傳遞單一事件。 您必須負責處理此事件。 如果您想要確定取用者會處理每個訊息至少一次,則必須自行撰寫具有重試邏輯的程式碼。 但請留意有害訊息。

建議您以相對快速的方式進行。 也就是說,盡量減少處理。 如果您需要寫入至儲存體並進行一些路由傳送,最好是使用兩個取用者群組,並且有兩個事件處理器。

Checkpoint

檢查點是事件處理器用來標記或認可資料分割內於最後成功處理事件的程序。 標記檢查點通常是在處理事件的函式中進行,而且是在取用者群組內的每個分割區上進行。

如果事件處理器與分割區中斷連線,另一個執行個體可以繼續處理檢查點上的分割區,此分割區由該取用者群組中該分割區的最後一個處理器所認可。 當處理器連線時,會將此位移傳遞給事件中樞,以指定要開始讀取的位置。 如此一來,您可以使用檢查點將事件標示為由下游應用程式「完成」,並在事件處理器中斷時提供復原功能。 縮短與此檢查點流程之間的位移可回到較舊的資料。

執行檢查點以將事件標示為已處理時,會使用事件的位移和序號來新增或更新檢查點存放區中的項目。 使用者應決定更新檢查點的頻率。 在每次成功處理事件之後更新,可能會影響效能和成本,因為會觸發對基礎檢查點存放區的寫入操作。 此外,每個單一事件的檢查點都表示佇列訊息模式,服務匯流排佇列可能是比事件中樞更好的選項。 事件中樞背後的構想是,在大型規模中您能取得「至少一次」的傳遞。 藉由讓您的下游系統具有等冪性,即可輕鬆地從失敗中復原,或以接收多次的相同事件重新啟動該結果。

使用 Azure Blob 記憶體做為檢查點存放區時,請遵循這些建議:

  • 針對每個取用者群組使用不同的容器。 您可以使用相同的記憶體帳戶,但每個群組各使用一個容器。
  • 請勿將容器用於任何其他項目,並請勿將儲存體帳戶用於任何其他項目。
  • 儲存體帳戶必須與部署應用程式位於相同的區域中。 如果應用程式是內部部署,請嘗試選擇最接近的區域。

在 Azure 入口網站的 [儲存體帳戶] 頁面上,於 [Blob 服務] 區段中,確定已停用下列設定。

  • 階層式命名空間
  • Blob 虛刪除
  • 版本控制

執行緒安全性和處理器執行個體

針對指定的分割區,系統預設會依序呼叫處理事件的函式。 相同分割區中的後續事件和對此函式的呼叫會在幕後排入佇列,因為事件抽取會繼續在其他執行緒的背景中執行。 您可以同時處理來自不同分割區的事件,而在分割區之間存取的任何共用狀態都必須同步。

下一步

請參閱下列快速入門: