IL-0579 Classi · 2026-11-11 (게시일)databaseaws
Elasticsearch 6.8 에서 OpenSearch 1.3 으로 옮긴 뒤 포트폴리오 검색의 응답 시간이 간헐적으로 1초 가까이 튀었다
Classi 는 포트폴리오 기능에 학생이 학교생활 중 기록한 데이터를 쌓고, 이를 검색하려고 Amazon OpenSearch Service 를 쓴다. 검색 엔진을 Elasticsearch 6.8 에서 OpenSearch 1.3 으로 옮기면서 Ruby 클라이언트를 elasticsearch-model 과 elasticsearch-rails 에서 opensearch-ruby 로, 인스턴스 타입을 m5.large.search 에서 AWS Graviton 기반의 m7g.large.search 로 함께 바꿨다. 문서 3,000만 건 이상은 기존 Elasticsearch 도메인의 스냅샷을 새 OpenSearch 도메인에 복원해 옮겼다.
옮긴 뒤 검색 처리의 최대 응답 시간이 이전의 100ms 정도에서 1초 안팎까지 간헐적으로 튀었다. 팀은 Slow Log 와 Profile API 로 쿼리 처리를 보고, HTTP 클라이언트 설정과 GC 를 확인하고, curl 로 직접 검색해 봤지만 원인을 찾지 못했다. 언제 느려지는지를 살피다가 문서를 갱신한 뒤의 검색이 늦어진다는 가설을 세웠고, refresh_interval 을 명시해 3s 로 설정하자 지연이 크게 줄었다. 1s 로 명시해도 개선이 유지되어 운영 환경에도 1s 로 명시해 설정했고, 그 뒤 간헐적인 지연이 사라졌다.
원인은 Search Idle 이었다. Elasticsearch 6.x 까지는 refresh_interval 을 정하지 않아도 1초마다 Refresh 가 돌았다. Elasticsearch 7.0 에서 들어온 Search Idle 은 refresh_interval 이 명시되지 않으면 일정 시간 검색되지 않은 샤드를 Idle 상태로 두고 백그라운드 Refresh 를 멈춘다. Elasticsearch 7.10 을 바탕으로 한 OpenSearch 도 이 동작을 물려받았고, index.search.idle.after 의 기본값은 30s 다. Idle 상태의 샤드에 검색이 들어왔을 때 Refresh 가 필요하면 첫 검색은 Refresh 가 끝날 때까지 기다린다. refresh_interval 을 명시하면 샤드가 이 제어에서 빠져 정한 간격으로 Refresh 된다.
- 심각도
- –
- 영향 범위
- Search for the Portfolio feature: maximum search latency intermittently about 1 second instead of about 100ms
- 영향 사용자
- –
- 지역
- –
- 감지까지
- –
- 복구까지
- –
증상
OpenSearch 1.3 으로 옮긴 뒤 동작을 확인하던 중 팀은 검색 응답이 가끔 크게 늦어지는 것을 알아챘다. 평소에는 응답이 정상으로 돌아왔고, 일정한 빈도로 응답 시간이 크게 튀었다.
Datadog APM 에서 검색 처리의 최대 응답 시간을 옮기기 전후로 비교했다. Elasticsearch 6.8 을 쓰던 기간에는 대체로 100ms 정도였고, OpenSearch 1.3 으로 옮긴 뒤에는 1초 안팎까지 올라가는 경우가 간헐적으로 생겼다. 평소의 응답 시간이 전체적으로 나빠진 것은 아니었다.
쿼리 자체가 느린지 먼저 의심했다. Slow Log 의 기준값을 0ms 로 두고 모든 쿼리를 기록해 애플리케이션에서 늦어진 시각과 맞춰 봤지만, 그 지연에 해당하는 쿼리 처리 시간은 보이지 않았다.
Search API 의 profile=true 로 처리 내역을 봤다. 늦어진 한 요청에서 애플리케이션이 잰 처리 시간은 867.5ms, OpenSearch 응답의 took 은 839ms 였지만, 샤드별 쿼리 처리 시간은 모두 1ms 미만이었다.
다음으로 애플리케이션과 OpenSearch 사이의 통신을 의심했다. Keep-Alive 와 idle_timeout 설정, Faraday 의 HTTP Adapter 를 바꿔 보고 OpenSearch 쪽 GC 도 확인했지만, 어느 것도 응답 시간과 뚜렷한 관련이 없었다. curl 로 Search API 를 직접 불렀을 때 같은 쿼리를 연달아 실행하면 첫 번째만 늦은 경우가 있었지만 재현되지 않았다.
팀은 어디가 느린지가 아니라 언제 느려지는지를 보기로 하고 검색과 갱신을 되풀이했다. 문서를 추가하거나 갱신한 뒤에 검색하면 응답 시간이 커질 수 있다는 가설이 나왔다.
증상 지연 시간 증가
원인
- 촉발
- 포트폴리오 기능의 검색 엔진을 Elasticsearch 6.8 에서 Amazon OpenSearch Service 의 OpenSearch 1.3 으로 옮겼다.
감지
OpenSearch 1.3 으로 옮긴 뒤 동작을 확인하던 중 팀이 검색 응답이 가끔 크게 늦어지는 것을 알아챘다. Datadog APM 에서 검색 처리의 최대 응답 시간을 옮기기 전후로 비교해 간헐적인 지연을 확인했다.
조치
- Refresh 빈도를 낮췄을 때의 변화를 보려고 refresh_interval 을 명시해 3s 로 설정했고, 검색 응답 시간이 튀는 일이 크게 줄었다.
- 1s 로 명시해도 개선이 유지되는 것을 확인한 뒤 운영 환경에서도 refresh_interval 을 명시해 1s 로 설정했다.
후속 조치
–
교훈
OpenSearch 응답의 took 이 커져 있었으므로 더 일찍 OpenSearch 쪽으로 조사 범위를 좁힐 수 있었다고 팀은 돌아봤다. Slow Log 와 Profile API 만으로는 원인을 찾지 못했고, 어디가 느린지에서 언제 느려지는지로 관점을 바꾼 것이 개선의 계기였다. 버전에 따라 같은 설정 값이라도 동작이 다르므로 기본 동작까지 확인해야 한다고 정리했다.
출처
관련 사례
–
내 클러스터에도 있는지 확인하기
AI 도구와 스크립트용
- 이 사례의 JSON: https://incidentlib-api.benchlet.com/cases/IL-0579
- 가장 비슷한 사례들: https://incidentlib-api.benchlet.com/cases/IL-0579/similar
- MCP 서버(Streamable HTTP, 키 없음):
https://incidentlib-mcp.benchlet.com/mcp
API 는 키가 필요 없습니다. MCP 서버는 search_incidents, get_incident, list_incidents, get_topic, vocab 도구를 내놓습니다. 사용법은 API 와 MCP.