1 분 소요

개발 동기

Elasticsearch든 MySQL이든 서버와 분리된 저장소에서 쿼리를 통해 데이터를 가져오는 방식이기 때문에 모든 케이스를 검증하기 어렵다. 요청값이 다양할 수록 확인해야하는 케이스도 기하급수로 많아질거고, 테스트하는 시간도 오래걸린다. 그리고 테스트에서 사용한 입력값이 운영 환경에서 발생하는 모든 케이스를 체크한다고 보장할 수 없다.

  • 일부 케이스를 누락해서 장애로 이어졌던 사례도 있었다.

그래서 API 호출될 때마다 적잘한 응답을 내려주는지 검증하고 실패하면 알람을 발생시켜 빠른 후속 조치가 가능하도록 개선하면 좋겠다고 생각했다.

아래는 참조했던 검증 관련 글/영상들이다. 그대로 사용할 일은 없었지만 많이 도움됐다.

구현

검증하는 방법은 간단하다. ES, MySQL에서 조회한 결과를 가져와서 일치하는지 확인하면 된다.

?
  • 스레드를 분리한 이유는 이벤트를 발행해서 검증 요청을 하기 때문이다. 검증하는 시간이 API 응답 시간에 큰 영향을 주지 않아야 한다.
  • 이벤트에는 검증에 필요한 값과 ES 쿼리, request 정보를 담아서 전달한다.
    • 검증 실패 시 메신저로 쿼리와 request 정보를 알람으로 보내 디버깅에 활용한다.

성과

충분한 기간동안 ES 쿼리에 이상이 없는지 검증하면서 안정성을 확인할 수 있었다.
테스트 코드만으로 문제가 없다고 확신을 갖기가 힘들었는데 검증기를 통해 어느정도 해소가 되었다고 생각한다.

발생했던 문제점과 한계점

데이터를 보관하는 곳이 2개로 늘어났기 때문에 동기화 작업이 필요하다. (ES <> MySQL)

ES는 인덱싱 속도가 빨라서 실시간성을 보장한다고 하지만, 모종의 이유로 인덱싱이 안되거나 느린 상황이라면 장시간동안 정상 응답을 기대할 수 없다.
인덱싱이 충분히 빨라도 MySQL에서 트랜잭션이 끝나자마자 ES 인덱싱이 완료된다고 보장할 수 없다.

하지만 검증기는 요청을 받자마자 검증 시도를 하기때문에 쿼리가 잘못되지 않았음에도 검증에 실패할 수 있다. (False Positive)

?
  • 이런 알람을 줄이기 위해 요청값에 오늘이 포함된 기간으로 검색한 경우는 제외했다.
    • 경험상 오늘 생성된 데이터는 변동 가능성이 매우 높았다.

오늘을 제외하지 않고, 검증을 몇 초 뒤에 하면 되는 것 아닌가? 라는 생각도 해봤지만, 안타깝게도 의미가 적은 시도라고 생각했다.

?
  • 계속 수정될 수 있는 동적 데이터이기 때문이다. 심지어 언제 수정될지 예측할 수 없어서 바뀌는 타이밍을 모두 제어하기 어렵다.
  • 사실 이 문제는 오늘을 제외해도 발생하는 문제다. 하지만 잘못된 알람을 많이 줄일 수 있었다.

추가로 개선했으면 좋았을 것들

circuit breaker 적용

(다행히도 새 ES 쿼리에 오류는 없었지만) ES 쿼리가 잘못됐었다면 롤백하는 방법밖에 없었어서, 잘못된 결과를 내려줬을 때 대처 방안이 너무 미비했다. circuit breaker를 통해 MySQL로 우회하도록 작업을 해뒀다면 좋았을 것 같다.

  • 단, False Positive가 거의 없도록 개선이 필요하다. 시도때도 없이 open되면 곤란하다.
  • ES 쿼리가 잘못됐을 때 뿐만 아니라 ES 장애가 발생했을 때도 대응이 가능하다.

카나리 배포 전략

검증에 실패해서 발생했던건 아니지만 배포 후 장애가 크게 발생한 적이 있었는데, 카나리 배포 전략을 사용했다면 장애 영향을 크게 줄일 수 있었을 것 같다.

카테고리:

업데이트:

댓글남기기