본문 바로가기
WIKI 기술 지식 베이스

Search backpressure

원문 보기 위키 갱신

출처: 문서

본문

검색 백프레셔

검색 백프레셔는 리소스를 많이 소모하는 검색 요청을 식별하고, 노드가 부담 상태에 있을 때 해당 요청을 취소하기 위한 메커니즘이에요. 노드나 샤드에서 실행 중인 검색 요청이 리소스 한도를 초과한 뒤 일정 기준 안에 회복되지 않으면, 해당 요청은 거절돼요. 이러한 임계값은 동적이며, /_cluster/settings API 엔드포인트를 사용하는 클러스터 설정을 통해 구성할 수 있어요.

리소스 소비 측정

검색 백프레셔를 적용할지 여부를 판단하기 위해, OpenSearch는 각 검색 요청에 대해 다음과 같은 리소스 소비 통계를 주기적으로 측정해요:

  • CPU 사용량
  • 힙 사용량
  • 경과 시간

옵저버 스레드가 노드의 리소스 사용량을 주기적으로 측정해요. OpenSearch는 노드가 부담 상태에 있다고 판단하면, 각 검색 작업(search task)과 검색 샤드 작업(search shard task)의 리소스 사용량을 살펴보고 설정 가능한 임계값과 비교해요. OpenSearch는 CPU 사용량, 힙 사용량, 경과 시간을 종합적으로 고려해 각 작업에 취소 점수(cancellation score)를 부여하고, 이 점수를 사용해 리소스를 가장 많이 소모하는 작업부터 취소해요.

OpenSearch는 취소 횟수를 성공적으로 완료된 작업 수의 일정 비율로 제한해요. 또한 단위 시간당 취소 횟수도 제한해요. OpenSearch는 노드가 더 이상 부담 상태가 아닐 때까지 작업 모니터링과 취소를 계속해요.

취소된 쿼리

쿼리가 취소된 경우, 일부 샤드만 실패했다면 OpenSearch는 부분 결과를 반환할 수 있어요. 모든 샤드가 실패했다면 OpenSearch는 서버에서 다음과 유사한 오류를 반환해요:

{
  "error": {
    "root_cause": [
      {
          "type": "task_cancelled_exception",
          "reason": "cancelled task with reason: cpu usage exceeded [17.9ms >= 15ms], elapsed time exceeded [1.1s >= 300ms]"
      },
      {
          "type": "task_cancelled_exception",
          "reason": "cancelled task with reason: elapsed time exceeded [1.1s >= 300ms]"
      }
    ],
    "type": "search_phase_execution_exception",
    "reason": "all shards failed",
    "phase": "query",
    "grouped": true,
    "failed_shards": [
      {
        "shard": 0,
        "index": "foobar",
        "node": "7yIqOeMfRyWW1rHs2S4byw",
        "reason": {
            "type": "task_cancelled_exception",
            "reason": "cancelled task with reason: cpu usage exceeded [17.9ms >= 15ms], elapsed time exceeded [1.1s >= 300ms]"
        }
      },
      {
        "shard": 1,
        "index": "foobar",
        "node": "7yIqOeMfRyWW1rHs2S4byw",
        "reason": {
            "type": "task_cancelled_exception",
            "reason": "cancelled task with reason: elapsed time exceeded [1.1s >= 300ms]"
        }
      }
    ]
  },
  "status": 500
}

검색 백프레셔 모드

검색 백프레셔는 monitor_only(기본값), enforced, disabled 모드 중 하나로 동작해요. enforced 모드에서는 서버가 검색 요청을 거절해요. monitor_only 모드에서는 서버가 실제로 검색 요청을 취소하지는 않지만, 관련 통계를 추적해요. 모드는 search_backpressure.mode 파라미터에서 지정할 수 있어요.

검색 백프레셔 설정

검색 백프레셔는 표준 OpenSearch 클러스터 설정에 여러 설정을 추가해요. 이 설정들은 동적이므로, 클러스터를 재시작하지 않고도 이 기능의 기본 동작을 변경할 수 있어요.

이 설정들을 구성하려면 /_cluster/settings로 PUT 요청을 보내세요:

PUT /_cluster/settings
{
  "persistent": {
    "search_backpressure": {
      "mode": "monitor_only"
    }
  }
}

{% include copy-curl.html %}

설정 기본값 설명
search_backpressure.mode monitor_only 검색 백프레셔 모드예요. 유효한 값은 monitor_only, enforced, disabled이에요.
search_backpressure.cancellation_ratio
2.6에서 지원 중단됨. search_backpressure.search_shard_task.cancellation_ratio로 대체됨
10% 성공적으로 완료된 작업 수를 기준으로, 취소할 수 있는 최대 작업 수(백분율)예요.
search_backpressure.cancellation_rate
2.6에서 지원 중단됨. search_backpressure.search_shard_task.cancellation_rate로 대체됨
0.003 경과 시간 밀리초당 취소할 수 있는 최대 작업 수예요.
search_backpressure.cancellation_burst
2.6에서 지원 중단됨. search_backpressure.search_shard_task.cancellation_burst로 대체됨
10 옵저버 스레드의 한 번의 반복에서 취소할 수 있는 검색 샤드 작업의 최대 개수예요.
search_backpressure.node_duress.num_successive_breaches 3 노드가 부담 상태로 간주되기 위해 연속적으로 한도를 초과해야 하는 횟수예요.
search_backpressure.node_duress.cpu_threshold 90% 노드가 부담 상태로 간주되기 위해 필요한 CPU 사용량 임계값(백분율)이에요.
search_backpressure.node_duress.heap_threshold 70% 노드가 부담 상태로 간주되기 위해 필요한 힙 사용량 임계값(백분율)이에요.
search_backpressure.search_task.elapsed_time_millis_threshold 45,000 개별 부모 작업이 취소 대상으로 고려되기까지 필요한 경과 시간 임계값(밀리초)이에요.
search_backpressure.search_task.cancellation_ratio 0.1 성공적으로 완료된 검색 작업 수를 기준으로, 취소할 수 있는 검색 작업의 최대 개수(백분율)예요. 값 범위는 (0, 1]이에요.
search_backpressure.search_task.cancellation_rate 0.003 경과 시간 밀리초당 취소할 수 있는 검색 작업의 최대 개수예요. 값은 0보다 커야 해요.
search_backpressure.search_task.cancellation_burst 5 옵저버 스레드의 한 번의 반복에서 취소할 수 있는 검색 작업의 최대 개수예요. 값은 1보다 크거나 같아야 해요.
search_backpressure.search_task.heap_percent_threshold 2% 개별 부모 작업이 취소 대상으로 고려되기까지 필요한 힙 사용량 임계값(백분율)이에요. 값 범위는 [0%, 100%]예요.
search_backpressure.search_task.total_heap_percent_threshold 5% 취소가 적용되기까지 모든 검색 작업의 힙 사용량 합계가 충족해야 하는 힙 사용량 임계값(백분율)이에요. 값 범위는 [0%, 100%]예요.
search_backpressure.search_task.heap_variance 2.0 개별 부모 작업이 취소 대상으로 고려되기까지 필요한 힙 사용량 분산이에요. taskHeapUsage가 heapUsageMovingAverage * variance보다 크거나 같으면 해당 작업은 취소 대상으로 고려돼요. 값은 0보다 크거나 같아야 해요.
search_backpressure.search_task.heap_moving_average_window_size 10 완료된 부모 작업들의 힙 사용량 이동 평균을 계산하는 데 사용되는 윈도우 크기예요. 값은 0보다 크거나 같아야 해요.
search_backpressure.search_task.cpu_time_millis_threshold 30,000 개별 부모 작업이 취소 대상으로 고려되기까지 필요한 CPU 사용량 임계값(밀리초)이에요. 값은 0보다 크거나 같아야 해요.
search_backpressure.search_shard_task.elapsed_time_millis_threshold 30,000 개별 검색 샤드 작업이 취소 대상으로 고려되기까지 필요한 경과 시간 임계값(밀리초)이에요. 값은 0보다 크거나 같아야 해요.
search_backpressure.search_shard_task.cancellation_ratio 0.1 성공적으로 완료된 검색 샤드 작업 수를 기준으로, 취소할 수 있는 검색 샤드 작업의 최대 개수(백분율)예요. 값 범위는 (0, 1]이에요.
search_backpressure.search_shard_task.cancellation_rate 0.003 경과 시간 밀리초당 취소할 수 있는 검색 샤드 작업의 최대 개수예요. 값은 0보다 커야 해요.
search_backpressure.search_shard_task.cancellation_burst 10 옵저버 스레드의 한 번의 반복에서 취소할 수 있는 검색 샤드 작업의 최대 개수예요. 값은 1보다 크거나 같아야 해요.
search_backpressure.search_shard_task.heap_percent_threshold 0.5% 개별 검색 샤드 작업이 취소 대상으로 고려되기까지 필요한 힙 사용량 임계값(백분율)이에요. 값 범위는 [0%, 100%]예요.
search_backpressure.search_shard_task.total_heap_percent_threshold 5% 취소가 적용되기까지 모든 검색 샤드 작업의 힙 사용량 합계가 충족해야 하는 힙 사용량 임계값(백분율)이에요. 값 범위는 [0%, 100%]예요.
search_backpressure.search_shard_task.heap_variance 2.0 개별 검색 샤드 작업의 힙 사용량이, 이전에 완료된 작업들의 이동 평균과 비교했을 때 취소 대상으로 고려되기까지 필요한 최소 분산이에요. 값은 0보다 크거나 같아야 해요.
search_backpressure.search_shard_task.heap_moving_average_window_size 100 힙 사용량의 이동 평균을 계산할 때 고려할, 이전에 완료된 검색 샤드 작업의 개수예요. 값은 0보다 크거나 같아야 해요.
search_backpressure.search_shard_task.cpu_time_millis_threshold 15,000 개별 검색 샤드 작업이 취소 대상으로 고려되기까지 필요한 CPU 사용량 임계값(밀리초)이에요. 값은 0보다 크거나 같아야 해요.

검색 백프레셔 통계 API

2.4에 도입됨 {: .label .label-purple }

노드 통계 API 작업를 사용하면 서버 측 요청 취소를 모니터링할 수 있어요.

요청 예제

통계를 조회하려면 다음 요청을 사용하세요:

GET _nodes/stats/search_backpressure

응답 예제

응답에는 서버 측 요청 취소 통계가 담겨 있어요:

{
  "_nodes": {
    "total": 1,
    "successful": 1,
    "failed": 0
  },
  "cluster_name": "runTask",
  "nodes": {
    "T7aqO6zaQX-lt8XBWBYLsA": {
      "timestamp": 1667409521070,
      "name": "runTask-0",
      "transport_address": "127.0.0.1:9300",
      "host": "127.0.0.1",
      "ip": "127.0.0.1:9300",
      "roles": [
         
      ],
      "attributes": {
        "testattr": "test",
        "shard_indexing_pressure_enabled": "true"
      },
      "search_backpressure": {
        "search_task": {
          "resource_tracker_stats": {
            "heap_usage_tracker": {
              "cancellation_count": 57,
              "current_max_bytes": 5739204,
              "current_avg_bytes": 962465,
              "rolling_avg_bytes": 4009239
            },
            "elapsed_time_tracker": {
              "cancellation_count": 97,
              "current_max_millis": 15902,
              "current_avg_millis": 9705
            },
            "cpu_usage_tracker": {
              "cancellation_count": 64,
              "current_max_millis": 8483,
              "current_avg_millis": 7843
            }
          },
          "cancellation_stats": {
            "cancellation_count": 102,
            "cancellation_limit_reached_count": 25
          }
        },
        "search_shard_task": {
          "resource_tracker_stats": {
            "heap_usage_tracker": {
              "cancellation_count": 34,
              "current_max_bytes": 1203272,
              "current_avg_bytes": 700267,
              "rolling_avg_bytes": 1156270
            },
            "cpu_usage_tracker": {
              "cancellation_count": 318,
              "current_max_millis": 731,
              "current_avg_millis": 303
            },
            "elapsed_time_tracker": {
              "cancellation_count": 310,
              "current_max_millis": 1305,
              "current_avg_millis": 649
            }
          },
          "cancellation_stats": {
            "cancellation_count": 318,
            "cancellation_limit_reached_count": 97
          }
        },
        "mode": "enforced"
      }
    }
  }
}

응답 본문 필드

응답에는 다음 필드가 담겨 있어요.

필드 이름 데이터 타입 설명
search_backpressure Object 검색 백프레셔에 대한 통계예요.
search_backpressure.search_task Object 검색 작업에 대한 통계예요. 개별 취소 기준(힙, CPU, 경과 시간)별 리소스 트래커 통계와 이 트래커들 전반의 모든 취소 활동에 대한 요약이 포함되어 있어요.
search_backpressure.search_task.resource_tracker_stats Object 트래커별 통계로, 각 리소스 타입(힙 사용량, CPU 사용량, 경과 시간)별 취소 횟수와 현재 리소스 소비 지표를 보여줘요.
search_backpressure.search_task.cancellation_stats Object 모든 리소스 트래커에 걸친 집계된 취소 통계예요. cancellation_count와 cancellation_limit_reached_count의 합은 모든 리소스 트래커 취소 횟수의 총합과 같아요.
search_backpressure.search_shard_task Object 검색 샤드 작업에 대한 통계예요. 개별 취소 기준(힙, CPU, 경과 시간)별 리소스 트래커 통계와 이 트래커들 전반의 모든 취소 활동에 대한 요약이 포함되어 있어요.
search_backpressure.search_shard_task.resource_tracker_stats Object 트래커별 통계로, 각 리소스 타입(힙 사용량, CPU 사용량, 경과 시간)별 취소 횟수와 현재 리소스 소비 지표를 보여줘요.
search_backpressure.search_shard_task.cancellation_stats Object 모든 리소스 트래커에 걸친 집계된 취소 통계예요. cancellation_count와 cancellation_limit_reached_count의 합은 모든 리소스 트래커 취소 횟수의 총합과 같아요.
search_backpressure.mode String 검색 백프레셔의 모드예요.

resource_tracker_stats

resource_tracker_stats 객체에는 각 리소스 트래커에 대한 통계가 담겨 있어요: elapsed_time_tracker, heap_usage_tracker, cpu_usage_tracker.

elapsed_time_tracker

elapsed_time_tracker 객체에는 경과 시간과 관련된 다음 통계가 담겨 있어요.

필드 이름 데이터 타입 설명
cancellation_count Integer 노드가 마지막으로 재시작된 이후 과도한 경과 시간으로 인해 취소로 표시된 작업 수예요.
current_max_millis Integer 현재 노드에서 실행 중인 모든 작업의 최대 경과 시간으로, 밀리초 단위예요.
current_avg_millis Integer 현재 노드에서 실행 중인 모든 작업의 평균 경과 시간으로, 밀리초 단위예요.

heap_usage_tracker

heap_usage_tracker 객체에는 힙 사용량과 관련된 다음 통계가 담겨 있어요.

필드 이름 데이터 타입 설명
cancellation_count Integer 노드가 마지막으로 재시작된 이후 과도한 힙 사용량으로 인해 취소로 표시된 작업 수예요.
current_max_bytes Integer 현재 노드에서 실행 중인 모든 작업의 최대 힙 사용량으로, 바이트 단위예요.
current_avg_bytes Integer 현재 노드에서 실행 중인 모든 작업의 평균 힙 사용량으로, 바이트 단위예요.
rolling_avg_bytes Integer 가장 최근 n개 작업의 이동 평균 힙 사용량으로, 바이트 단위예요. n은 설정할 수 있으며 search_backpressure.search_shard_task.heap_moving_average_window_size 설정으로 정의돼요. 이 설정의 기본값은 100이에요.

cpu_usage_tracker

cpu_usage_tracker 객체에는 CPU 사용량과 관련된 다음 통계가 담겨 있어요.

필드 이름 데이터 타입 설명
cancellation_count Integer 노드가 마지막으로 재시작된 이후 과도한 CPU 사용량으로 인해 취소로 표시된 작업 수예요.
current_max_millis Integer 현재 노드에서 실행 중인 모든 작업의 최대 CPU 시간으로, 밀리초 단위예요.
current_avg_millis Integer 현재 노드에서 실행 중인 모든 작업의 평균 CPU 시간으로, 밀리초 단위예요.

cancellation_stats

cancellation_stats 객체에는 취소로 표시된 작업에 대한 다음 통계가 담겨 있어요.

필드 이름 데이터 타입 설명
cancellation_count Integer 노드가 마지막으로 재시작된 이후 취소로 표시된 작업의 총 수예요.
cancellation_limit_reached_count Integer 취소 대상 작업 수가 설정된 취소 임계값을 초과한 횟수예요.

각 리소스 트래커(힙, CPU, 경과 시간)는 자신의 임계값을 초과하는 작업을 독립적으로 식별하고 자체 cancellation_count를 증가시켜요. 하나의 작업이 여러 리소스 임계값을 초과할 수 있기 때문에, 리소스 트래커 cancellation_count 값들의 합은 최상위 cancellation_count를 초과할 수 있어요. 최상위 cancellation_count는 실제로 취소된 고유 작업 수를 나타내요. cancellation_limit_reached_count는 옵저버 반복 중 취소 속도 제한에 도달하면 증가하며, 해당 반복에서 추가 취소가 일어나지 않도록 해요. {: .note}

더 알아보기 (Learn more)