블로그

배포 시 502 오류를 0개로 줄인 방법

Mythex 백엔드를 배포할 때마다 소수의 요청이 502 Bad Gateway로 실패했습니다. 많지는 않았지만, 배포 중의 502는 누군가의 클릭이 아무 일도 하지 않았다는 뜻이거나, 지켜보던 빌드가 잠깐 멈췄다는 뜻입니다. 우리는 이를 두 가지 별개의 문제로 추적했습니다. 배포와 싸우던 자가 치유 워치독, 그리고 서버가 수신을 멈춘 시점과 로드 밸런서가 그 서버로 트래픽 보내기를 멈춘 시점 사이의 간극입니다. 수정 후 연속된 세 번의 프로덕션 배포에서 그 수는 10, 6, 그리고 0으로 줄었습니다.

구성

API와 오케스트레이터는 AWS Application Load Balancer(ALB) 뒤의 작은 서버 그룹에서 컨테이너로 실행됩니다. 배포는 한 번에 한 서버씩 업데이트합니다. 오래된 컨테이너를 드레인하고, 새 컨테이너를 시작하고, 다음 서버로 넘어갑니다. 각 서버의 워치독은 컨테이너가 실행 중인지 확인하고, 실행되지 않는 것은 재시작합니다. 새벽 3시에 충돌한 프로세스가 아무도 깨지 않고 되살아나도록 존재합니다.

둘 다 그 자체로는 합리적입니다. 하지만 함께 놓이면 문제가 됩니다.

문제 1: 워치독이 배포와 경쟁했습니다

워치독은 1분마다 실행되었고, 헬스 체크가 한 번 실패하면 “치유”를 했습니다. 그런데 배포는 서비스를 최대 150초 동안 의도적으로 드레인합니다. 이 시간 동안 헬스 체크는 실패하는 것이 정상입니다. 그래서 워치독은 배포할 때마다 발동했습니다.

대부분은 경쟁에서 져서 아무 해가 없었습니다. 한 번은 이겼습니다. 배포 도중 컨테이너 구성 파일(어떤 컨테이너가 실행되어야 하는지 설명하는 파일)을 다시 쓰는 바람에, 게이트웨이 컨테이너가 전혀 없는 서버가 남았습니다. 그런데도 배포 작업은 성공으로 보고했습니다.

수정 사항은 다음과 같습니다.

  • 락 하나. 이제 배포는 서버 부트스트랩 스크립트와 같은 파일 락을 사용하므로, 워치독과 배포가 동시에 실행될 수 없습니다.
  • 한 번이 아니라 네 번. 워치독은 헬스 체크가 연속으로 네 번 실패해야 행동합니다. 드레인 중인 서비스가 더 이상 죽은 것처럼 보이지 않습니다.
  • 정의는 하나. 구성 파일은 이제 서버에 게시되는 단 하나의 원본을 가집니다. 어긋날 수 있는 여러 복사본이 없습니다.
  • 믿지 말고 확인하세요. 배포 작업은 명령이 반환되었다는 이유로 통과하지 않습니다. 성공하기 전에 모든 서버의 API, 오케스트레이터, 게이트웨이, 게시 워커를 확인합니다.

문제 2: 트래픽이 떠나기 전에 서버가 떠났습니다

두 번째 문제는 더 조용했습니다. 배포가 서버를 드레인할 때, 서버는 로드 밸런서가 서버를 로테이션에서 빼도록 헬스 엔드포인트에서 503을 반환하기 시작합니다. 우리 서버는 5초 동안 그렇게 한 뒤 종료했습니다.

그러나 ALB는 헬스를 가끔씩만 확인했고, 대상에게 라우팅을 멈추기 전에 연속으로 여러 번 실패해야 했습니다. 전체적으로 약 60초가 걸릴 수 있었습니다. 그래서 약 55초 동안 로드 밸런서는 이미 수신을 멈춘 서버로 실제 요청을 계속 보냈습니다. 그것이 우리의 502였습니다.

수정은 두 시간표를 맞추는 것이었습니다.

  • 대상 그룹은 이제 5초마다 확인하고, 2번 실패하면 대상을 비정상으로 표시합니다. 알아채기까지 약 10초가 걸립니다.
  • 드레인은 헬스 체크가 실패하기 시작한 뒤에도 15초 동안 실제 트래픽을 계속 처리합니다. 그래서 항상 겹치는 구간이 있습니다.
  • 이 설정들은 누군가 콘솔에서 한 번 클릭해 둔 곳이 아니라, 인프라를 프로비저닝하는 스크립트에 있습니다.

숫자들이 서로를 지키게 만들기

이런 시간 제한은 서로에게 의존합니다. 드레인은 로드 밸런서가 알아채는 데 걸리는 시간보다 길어야 하고, 드레인과 종료를 합친 시간은 컨테이너가 강제 종료되기 전에 끝나야 합니다. 누군가 6개월 뒤에 숫자 하나를 바꾸면서 조용히 버그를 되살리기 쉽습니다.

그래서 이 관계들을 테스트로 기록했습니다. 드레인은 헬스 체크 간격에 실패 임계값을 곱한 값보다 길어야 하고, 다시 정상으로 표시되기까지의 시간은 짧게 유지되어야 하며, 전체 드레인은 컨테이너의 정지 유예 시간 안에 들어가야 합니다. 숫자 하나만 바꾸고 나머지를 그대로 두면 CI가 실패합니다. 테스트 자체도 변이 테스트로 검증했습니다. 각 숫자를 잘못된 값으로 바꿔 보고, 테스트가 그것을 잡아내는지 확인했습니다.

배포를 측정하기는 쉽게 틀립니다

우리의 첫 측정은 깔끔한 배포가 약 3%가 깨졌다고 말했습니다. 사실이 아니었습니다. 우리는 200이 아닌 모든 응답을 세고 있었는데, 드레인 중 헬스 엔드포인트의 503은 실패가 아니라 드레인이 제 역할을 하는 것입니다. 로드 밸런서에게 실제 요청을 계속 처리하는 동안 그 서버를 선택하지 말라고 알리는 것입니다.

사용자가 체감하는 것은 502입니다. 요청이 아무것도 도달하지 못한 경우입니다. 그것만 세자 실제 상황이 보였습니다. 프로덕션 배포 세 번에 걸쳐 10, 6, 그리고 0이었습니다.

우리가 얻은 교훈

  • 자가 치유는 계획된 다운타임을 알아야 합니다. 배포와 충돌을 구분하지 못하는 워치독은 결국 배포와 싸우게 됩니다.
  • 드레인은 핸드셰이크입니다. 서버는 로드 밸런서가 트래픽을 보내지 않는다는 것이 확인될 때까지 계속 제공해야 하며, 그 타이밍은 서버가 아니라 로드 밸런서에서 설정됩니다.
  • 불변식을 테스트로 인코딩하세요. 운영 수치는 시간이 지나면서 어긋납니다. 서로를 관계로 묶는 테스트는 그렇지 않습니다.
  • 측정하기 전에 무엇을 측정할지 결정하세요. “오류”는 잘못된 지표였습니다. “아무것도 도달하지 못한 요청”이 올바른 지표였습니다.

Mythex에서 앱을 게시한다면 이 모든 것은 여러분에게 보이지 않습니다. 그것이 핵심입니다. 관련 글: 재게시하는 동안에도 게시된 앱이 계속 작동하는 방법.

Mythex · Pricing · AI로 무엇이든 만들기 · 웹사이트 및 앱 템플릿 · Mythex 비교 · AI 앱 개발 용어집 · 무료 AI 앱 개발 도구 · English

English አማርኛ العربية Български বাংলা Bosanski Català Čeština Dansk Deutsch Ελληνικά Español Español (España) Eesti فارسی Suomi Français Français (Canada) ગુજરાતી हिन्दी Hrvatski Magyar Հայերեն Bahasa Indonesia Íslenska Italiano 日本語 ქართული Қазақ тілі ಕನ್ನಡ Lietuvių Latviešu Македонски മലയാളം Монгол मराठी Bahasa Melayu မြန်မာ Norsk bokmål Nederlands ਪੰਜਾਬੀ Polski Português (Brasil) Português (Portugal) Română Русский Slovenčina Slovenščina Soomaali Shqip Srpski Svenska Kiswahili தமிழ் తెలుగు ไทย Tagalog Türkçe Українська اردو Tiếng Việt 简体中文 繁體中文(香港) 繁體中文(台灣)