如何防止 Elasticsearch 服務 OOM ?

infinilabs發表於2024-03-03

ES 和傳統關係型資料庫有很多區別, 比如傳統資料中普遍都有一個叫“最大連線數”的設定。目的是使資料庫系統工作在可控的負載下,避免出現負載過高,資源耗盡,誰也無法登入的局面。

那 ES 在這方面有類似引數嗎?答案是沒有,這也是為何 ES 會被流量打爆的原因之一。

針對大併發訪問 ES 服務,造成 ES 節點 OOM,服務中斷的情況,極限科技旗下的 產品(以下簡稱 “極限閘道器”)可從兩個方面入手,保障 ES 服務的可用性。

  1. 限制最大併發訪問連線數。
  2. 限制非重要索引的請求速度,保障重要業務索引的訪問速度。

下面我們來詳細聊聊。

架構圖


所有訪問 ES 的請求都發給閘道器,可部署多個閘道器。

限制最大連線數

在閘道器配置檔案中,預設有最大併發連線數限制,預設最大 10000。

entry:
  - name: my_es_entry
    enabled: true
    router: my_router
    max_concurrency: 10000
    network:
      binding: $[[env.GW_BINDING]]
      # See `gateway.disable_reuse_port_by_default` for more information.
      reuse_port: true

使用壓測程式測試,看看到達 10000 個連線後,能否限制新的連線。

超過的連線請求,被丟棄。更多資訊參考 。

限制索引寫入速度

我們先看看不做限制的時候,測試環境的寫入速度,在 9w - 15w docs/s 之間波動。雖然峰值很高,但不穩定。

接下來,我們透過閘道器把寫入速度控制在最大 1w docs/s 。
對閘道器的配置檔案 gateway.yml ,做以下修改。

env: # env 下新增
  THROTTLE_BULK_INDEXING_MAX_BYTES: 40485760 #40MB/s
  THROTTLE_BULK_INDEXING_MAX_REQUESTS: 10000 #10k docs/s
  THROTTLE_BULK_INDEXING_ACTION: retry #retry,drop
  THROTTLE_BULK_INDEXING_MAX_RETRY_TIMES: 10 #1000
  THROTTLE_BULK_INDEXING_RETRY_DELAY_IN_MS: 100 #10router: # route 部分修改 flow
  - name: my_router    default_flow: default_flow    tracing_flow: logging_flow    rules:
      - method:
          - "*"
        pattern:
          - "/_bulk"
          - "/{any_index}/_bulk"
        flow:
          - write_flowflow: #flow 部分增加下面兩段
  - name: write_flow    filter:
      - flow:
          flows:
            - bulking_indexing_limit      - elasticsearch:
          elasticsearch: prod          max_connection_per_node: 1000
  - name: bulking_indexing_limit    filter:
      - bulk_request_throttle:
          indices:
            "test-index":
              max_bytes: $[[env.THROTTLE_BULK_INDEXING_MAX_BYTES]]
              max_requests: $[[env.THROTTLE_BULK_INDEXING_MAX_REQUESTS]]
              action: $[[env.THROTTLE_BULK_INDEXING_ACTION]]
              retry_delay_in_ms: $[[env.THROTTLE_BULK_INDEXING_RETRY_DELAY_IN_MS]]
              max_retry_times: $[[env.THROTTLE_BULK_INDEXING_MAX_RETRY_TIMES]]
              message: "bulk writing too fast" #觸發限流告警message自定義
              log_warn_message: true

再次壓測,test-index 索引寫入速度被限制在了 1w docs/s 。

限制多個索引寫入速度

上面的配置是針對 test-index 索引的寫入速度控制。如果想新增其他的索引,新增一段配置即可。
比如,我允許 abc 索引寫入達到 2w docs/s,test-index 索引最多不超過 1w docs/s ,可配置如下。

- name: bulking_indexing_limit  filter:
    - bulk_request_throttle:
        indices:
          "abc":
            max_requests: 20000
            action: drop            message: "abc doc寫入超閾值" #觸發限流告警message自定義
            log_warn_message: true
          "test-index":
            max_bytes: $[[env.THROTTLE_BULK_INDEXING_MAX_BYTES]]
            max_requests: $[[env.THROTTLE_BULK_INDEXING_MAX_REQUESTS]]
            action: $[[env.THROTTLE_BULK_INDEXING_ACTION]]
            retry_delay_in_ms: $[[env.THROTTLE_BULK_INDEXING_RETRY_DELAY_IN_MS]]
            max_retry_times: $[[env.THROTTLE_BULK_INDEXING_MAX_RETRY_TIMES]]
            message: "bulk writing too fast" #觸發限流告警message自定義
            log_warn_message: true

限速效果如下

更多資訊參考 。

限制讀請求速度

我們先看看不做限制的時候,測試環境的讀取速度,7w qps 。

接下來我們透過閘道器把讀取速度控制在最大 1w qps 。
繼續對閘道器的配置檔案 gateway.yml 做以下修改。

  - name: default_flow    filter:
      - request_path_limiter:
          message: "Hey, You just reached our request limit!"                                      rules:
            - pattern: "/(?P<index_name>abc)/_search"
              max_qps: 10000
              group: index_name      - elasticsearch:
          elasticsearch: prod          max_connection_per_node: 1000

再次進行測試,讀取速度被限制在了 1w qps 。

限制多個索引讀取速度

上面的配置是針對 abc 索引的寫入速度控制。如果想新增其他的索引,新增一段配置即可。
比如,我允許 abc 索引讀取達到 1w qps,test-index 索引最多不超過 2w qps ,可配置如下。

- name: default_flow  filter:
    - request_path_limiter:
        message: "Hey, You just reached our request limit!"
        rules:
          - pattern: "/(?P<index_name>abc)/_search"
            max_qps: 10000
            group: index_name          - pattern: "/(?P<index_name>test-index)/_search"
            max_qps: 20000
            group: index_name    - elasticsearch:
        elasticsearch: prod        max_connection_per_node: 1000


多個閘道器限速

限速是每個閘道器自身的控制,如果有多個閘道器,那麼後端 ES 叢集收到的請求數等於多個閘道器限速的總和。

本次介紹就到這裡了。相信大家在使用 ES 的過程中也遇到過各種各樣的問題。歡迎大家來我們這個平臺分享自己的問題、解決方案等。如有任何問題,請隨時聯絡我,期待與您交流!

來自 “ ITPUB部落格 ” ,連結:https://blog.itpub.net/70029458/viewspace-3007930/,如需轉載,請註明出處,否則將追究法律責任。

相關文章