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}