針對事件處理器 Azure 事件中樞 進行疑難解答
本文提供使用 EventProcessorClient
類型時可能會遇到之常見問題的解決方案。 如果您要尋找使用 Azure 事件中樞 時可能會遇到之其他常見問題的解決方案,請參閱疑難解答 Azure 事件中樞。
當您使用事件處理器時發生 412 前置條件失敗
當客戶端嘗試取得或更新數據分割的擁有權時,會發生 412 前置條件錯誤,但本機版本的擁有權記錄已過期。 當另一個處理器實例竊取分割區擁有權時,就會發生此問題。 如需詳細資訊,請參閱一節。
分割區擁有權經常變更
當實例數目 EventProcessorClient
變更時(也就是新增或移除),執行中的實例會嘗試在本身之間負載平衡分割區。 在處理器數目變更后的幾分鐘內,數據分割應該會變更擁有者。 平衡之後,分割區擁有權應該穩定且不常變更。 如果分割區擁有權在處理器數目是常數時經常變更,則表示有問題。 建議您提出記錄和重現的 GitHub 問題。
分割區擁有權是透過 中的 CheckpointStore
擁有權記錄來決定。 在每個負載平衡間隔上,將會 EventProcessorClient
執行下列工作:
- 擷取最新的擁有權記錄。
- 檢查記錄,以查看哪些記錄尚未在分割區擁有權到期間隔內更新其時間戳。 只會考慮符合此準則的記錄。
- 如果有任何未擁有的數據分割,而且 實例
EventProcessorClient
之間的負載不平衡,事件處理器用戶端會嘗試宣告分割區。 - 更新擁有之數據分割的擁有權記錄,該數據分割具有該數據分割的作用中連結。
您可以透過 建立 EventProcessorClient
EventProcessorClientBuilder
時設定負載平衡和擁有權到期間隔,如下列清單所述:
- loadBalancingUpdateInterval(Duration) 方法會指出負載平衡週期的執行頻率。
- partitionOwnershipExpirationInterval (Duration) 方法表示在處理器將分割區視為未擁有之前,自擁有權記錄更新以來的最小時間量。
例如,如果擁有權記錄在上午 9:30 更新,且 partitionOwnershipExpirationInterval
為 2 分鐘。 當負載平衡周期發生且注意到擁有權記錄在最近 2 分鐘或上午 9:32 之間尚未更新,則會將分割區視為未擁有。
如果其中一個分割取用者發生錯誤,它會關閉對應的取用者,但在下一個負載平衡週期之前,不會嘗試回收它。
"...目前接收者 『RECEIVER_NAME>』 與 epoch '<0' 正在中斷連線」
整個錯誤訊息看起來類似下列輸出:
New receiver 'nil' with higher epoch of '0' is created hence current receiver 'nil' with epoch '0'
is getting disconnected. If you are recreating the receiver, make sure a higher epoch is used.
TrackingId:<GUID>, SystemTracker:<NAMESPACE>:eventhub:<EVENT_HUB_NAME>|<CONSUMER_GROUP>,
Timestamp:2022-01-01T12:00:00}"}
新增或移除實例之後發生負載平衡時 EventProcessorClient
,預期會發生此錯誤。 負載平衡是進行中的程式。 當您搭配取用者使用 BlobCheckpointStore
時,每約 30 秒(根據預設),取用者會檢查哪些取用者有每個分割區的宣告,然後執行一些邏輯來判斷它是否需要從另一個取用者「竊取」分割區。 用來判斷分割區獨佔擁有權的服務機制稱為 Epoch。
不過,如果未新增或移除任何實例,就應該解決基礎問題。 如需詳細資訊,請參閱 分割區擁有權經常 變更一節和 提出 GitHub 問題。
高 CPU 使用率
高 CPU 使用量通常是因為實例擁有太多分割區。 我們建議每個 CPU 核心不超過三個分割區。 最好從每個 CPU 核心的 1.5 個分割區開始,然後藉由增加擁有的數據分割數目進行測試。
記憶體不足,並選擇堆積大小
如果 JVM 目前的最大堆積不足以執行應用程式,記憶體不足 (OOM) 問題就可能發生。 您可能想要測量應用程式的堆積需求。 然後,根據結果,使用 -Xmx
JVM 選項設定適當的最大堆積記憶體來調整堆積大小。
您不應該將 指定 -Xmx
為大於主機可用記憶體或設定限制的值(例如,容器組態中要求的記憶體。 您應該為主機配置足夠的記憶體,以支援 Java 堆積。
下列步驟描述測量最大 Java 堆積值的一般方法:
在接近生產環境的環境中執行應用程式,其中應用程式會在生產環境預期的尖峰負載下傳送、接收及處理事件。
等候應用程式達到穩定狀態。 在這個階段,應用程式和 JVM 會載入所有網域對象、類別類型、靜態實例、物件集區 (TCP、DB 連線集區)等。
在穩定狀態下,您會看到堆積集合的穩定鋸形圖樣,如下列螢幕快照所示:
應用程式到達穩定狀態之後,使用 JConsole 之類的工具強制進行完整垃圾收集(GC)。 觀察完整 GC 之後所佔用的記憶體。 您想要調整堆積的大小,讓完整 GC 之後只佔用 30%。 您可以使用此值來設定堆積大小上限(使用
-Xmx
)。
如果您位於容器上,請將容器大小調整為具有額外 ~1 GB 記憶體,以供 JVM 實例所需的非堆積使用。
處理器用戶端停止接收
處理器用戶端通常會在主機應用程式中持續執行幾天。 有時候,它會注意到 EventProcessorClient
不會處理一或多個分割區。 通常沒有足夠的信息來判斷例外狀況發生的原因。 EventProcessorClient
停止是嘗試從暫時性錯誤中復原時發生之根本原因(也就是競爭狀況)的癥狀。 如需我們需要的資訊,請參閱 提出 GitHub 問題。
重新啟動處理器時收到的重複 EventData
和事件中 EventProcessorClient
樞服務保證至少傳遞一 次 。 您可以新增元資料來辨別重複的事件。 如需詳細資訊,請參閱 Stack Overflow 上的 Azure 事件中樞 保證至少傳遞一次嗎? 如果您只需要傳遞一次,您應該考慮 服務匯流排,以等候客戶端的認可。 如需傳訊服務的比較,請參閱 在 Azure 傳訊服務之間選擇。
從舊版移轉至新的用戶端連結庫
移 轉指南 包含從舊版用戶端移轉和移轉舊版檢查點的步驟。
下一步
如果本文中的疑難解答指引無法協助您在使用適用於 Java 的 Azure SDK 用戶端連結庫時解決問題,建議您在適用於 Java 的 Azure SDK GitHub 存放庫中提出問題。