如何對 Amazon OpenSearch Service 中的斷路器異常狀況進行疑難排解?

上次更新日期:2021 年 9 月 1 日

我正在嘗試傳送資料至我的 Amazon OpenSearch Service (Amazon Elasticsearch Service 的後繼者) 叢集。但是,我收到一個表示資料過大的斷路異常狀況錯誤。為什麼會發生這種情況,我該如何解決這個問題?

簡短描述

當請求達到 OpenSearch Service 節點時,斷路器會預估載入所需資料需要的記憶體量。然後,OpenSearch Service 會比較預估的大小與設定的堆積大小限制。如果您的資料預估大小大於可用堆積大小,則系統會終止查詢。因此,系統會擲回 CircuitBreakerException,以避免節點超載。

OpenSearch Service 會使用以下斷路器來避免 JVM OutofMemoryError 異常狀況:

  • 請求
  • Fielddata
  • 傳輸中請求
  • 客戶服務
  • 上層

注意:請務必瞭解是由這五個斷路器中的哪一個引發異常狀況,因為每個斷路器都有其調校需求。如需有關斷路器類型的詳細資訊,請參閱 Elasticsearch 網站上的斷路器設定

若要取得每個節點和每個斷路器目前的記憶體使用量,請使用以下命令:

GET _nodes/stats/breaker

此外,請注意,斷路器僅為盡力最佳機制。雖然斷路器會提供一些彈性以避免節點超載,但您最終可能仍會收到 OutofMemoryError。斷路器只有在明確預留記憶體時才能追蹤記憶體,因此並非總是能預估確切的記憶體使用量。例如,如果您有少量的記憶體堆積,則未追蹤記憶體的相對負擔會更大。如需有關斷路器和節點彈性的詳細資訊,請參閱 Elasticsearch 網站上的使用真正的記憶體斷路器以改善節點彈性

若要避免資料節點超載,請遵循對高 JVM 記憶體壓力進行疑難排解區段中提供的提示。

解決方案

斷路器異常狀況

如果您使用的是 Elasticsearch 7.x 及更高版本的 16 GB 堆積,在達到斷路器限制時,則會收到以下錯誤:

"error": {
        "root_cause": [
            {
                "type": "circuit_breaking_exception",
                "reason": "[parent] Data too large, data for [<http_request>] would be [16355096754/15.2gb], which is larger than the limit of [16213167308/15gb], real usage: [15283269136/14.2gb], new bytes reserved: [1071827618/1022.1mb]",
               }
      ]
}

此範例輸出表示要處理的資料太大,上層斷路器無法處理。上層斷路器 (斷路器類型) 負責叢集的整體記憶體使用量。發生上層斷路器異常狀況時,所有斷路器使用的記憶體總數已超過設定的限制。上層斷路器會在叢集超過 16 GB 的 95% (即 15.2 GB 的堆積) 時,拋出異常狀況。

您可以計算記憶體使用量與設定斷路器限制之間的差異,以驗證此邏輯。使用我們範例輸出的值,並從「[16213167308/15gb] 的限制」中減去「實際用量:[15283269136/14.2gb]」。此計算內容會顯示此請求需要大約 1.02 GB 的 新位元組預留記憶體,才能順利處理請求。不過,在此範例中,在資料請求進入時,叢集只有少於 0.8 GB 的可用記憶體堆積。因此,斷路器會跳閘。

斷路器異常狀況訊息可以此方式解釋:

  • [ ] 的資料: 用戶端會傳送 HTTP 請求至您集群中的節點。OpenSearch Service 會在本機處理請求,或將其傳遞到另一個節點進行其他處理。
  • 可能是 [#]:處理請求時,堆積大小為何。
  • [#] 的限制:目前斷路器限制。
  • 實際用量:JVM 堆積的實際用量。
  • 新位元組預留:處理請求所需的實際記憶體。

JVM 記憶體壓力

斷路器中斷異常狀況通常是因高 JVM 記憶體壓力所造成。JVM 記憶體壓力是指用於您叢集中所有資料節點的 Java 堆積百分比。檢查 Amazon CloudWatch 中的 JVMMemoryPressure 指標,以判斷目前用量。

注意:資料節點的 JVM 堆積大小已設定為實體記憶體 (RAM) 的一半,最多為 32 GB。例如,如果實體記憶體 (RAM) 是每個節點 128 GB,堆積大小將仍為 32 GB (最大堆積大小)。否則,堆積大小會以為實體記憶體的一半大小來計算。

高 JVM 記憶體壓力可能是由以下原因引起:

  • 增加對叢集的請求數。檢查 Amazon CloudWatch 中的 IndexRateSearchRate 指標,以判斷您目前的負載。
  • 彙總、萬用字元,以及在查詢中使用寬廣的時間範圍。
  • 節點中的碎片分配不平衡,或一個叢集中有太多碎片。
  • 索引映射劇增。
  • 使用 fielddata 資料結構來查詢資料。Fielddata 可以消耗大量堆積空間,並在區段生命週期中持續保留在堆積中。因此,使用 Fielddata 時,叢集上的 JVM 記憶體壓力將持續很高。如需詳細資訊,請參閱 Elasticsearch 網站上的 Fielddata

疑難排解高 JVM 記憶體壓力

若要解決高 JVM 記憶體壓力,請嘗試以下秘訣:

  • 減少叢集的傳入流量,尤其是在您的工作負載繁重時更是如此。
  • 考慮擴展叢集以取得更多 JVM 記憶體,以支援您的工作負載。
  • 如果不可能進行叢集擴展,請嘗試刪除舊的或未使用的索引來減少碎片數量。由於碎片中繼資料儲存在記憶體中,因此減少碎片數可降低整體記憶體用量。
  • 啟用慢速日誌以識別錯誤請求。
    注意:在啟用組態變更之前,請驗證 JVM 記憶體壓力低於 85%。如此一來,您就可以避免對現有資源增加其他負擔。
  • 最佳化搜尋和索引請求,並選擇正確的碎片數。如需有關索引和碎片數的詳細資訊,請參閱開始使用 Amazon OpenSearch Service:我需要幾個碎片?
  • 停用並避免使用 fielddata。 根據預設,除非 fielddata 在索引映射中有明確定義,否則其在文字欄為上會設為 "false"。
  • 使用 reIndex API建立或更新索引範本 API,將索引映射類型變更為關鍵字。您可以使用關鍵字類型作為對文字欄位執行彙總和排序的替代方案。
  • 避免在文字欄位上彙總,以避免欄位資料增加。在您使用更多欄位資料時,就會耗用更多的堆積空間。使用叢集統計資料 API 操作來檢查欄位資料。
  • 使用以下 API 呼叫來清除 fielddata 快取:
POST /index_name/_cache/clear?fielddata=true (index-level cache)
POST */_cache/clear?fielddata=true (cluster-level cache)

警告:如果您清除 fielddata 快取,任何進行中的查詢將可能中斷。

如需詳細資訊,請參閱如何對 Amazon OpenSearch Service 叢集上的高 JVM 記憶體壓力進行疑難排解?