지금 맡은 시스템은 24시간 돌아간다. 밤에도 새벽에도 사람이 쓴다.
그동안 일하던 곳은 대부분 낮에만 쓰는 서비스여서 새벽에 배포한다는 말이 통했다. 여기서는 안 통해서 몇 달 하면서 방법을 바꿔야 했던 것들을 적어 둔다.
Table of contents
Open Table of contents
제약 — 내릴 시간이 없다
처음에는 접속이 가장 적은 시간대를 찾아 거기에 배포 창을 잡으려 했다. access_log 를 시각별로 세어 보니 그런 시간대가 있긴 했는데 그때도 쓰는 사람이 몇 명은 있었다.
몇 명이 쓰고 있는데 서비스를 내리는 것이 맞나 싶어서 그 방향을 접었다. 결국 서비스를 내리지 않고 바꾸는 방법을 찾는 쪽으로 돌아섰다.
지금 하는 방식은 이렇다.
1. 새 버전을 띄운다 (아직 아무도 안 보냄)
2. 정상인지 확인한다
3. 조금씩 새 쪽으로 보낸다
4. 문제 없으면 전부 옮긴다
5. 옛 버전을 내린다
3 번과 4 번 사이에 두 버전이 함께 떠 있는 시간이 반드시 생긴다.
판단 기준 — 두 버전이 동시에 도는 조건
이 조건에서 제일 먼저 부딪히는 것이 DB 스키마였다. ADD COLUMN 은 괜찮은데 옛 버전이 그 컬럼을 모르니 읽지도 쓰지도 않고 그냥 지나가기 때문이다.
그런데 컬럼 이름을 바꾸거나 DROP COLUMN 을 하면 그 순간에 옛 버전이 깨진다. 배포 중에 잠깐이라도 옛 버전이 살아 있으면 그 잠깐 동안 오류가 그대로 나간다.
조치 — 세 번에 나눠서 바꿨다
그래서 한 번에 할 ALTER TABLE 을 세 번의 배포로 나눠서 넣기로 했다.
| 단계 | 하는 일 |
|---|---|
| 1차 배포 | 새 컬럼 추가. 코드는 양쪽 다 쓸 수 있게 |
| 2차 배포 | 새 컬럼만 쓰게 |
| 3차 배포 | 옛 컬럼 삭제 |
세 번 배포해야 해서 번거롭지만 이렇게 안 하면 배포 중에 오류가 난다.
되돌릴 수 있는지를 매번 따져 보는 습관도 이 방식에서 나온 것이다. 새 버전에 문제가 있으면 옛 버전으로 가야 하는데 DB 가 이미 바뀌었으면 코드만 되돌려도 못 돌아간다.
검증 — 로그 대신 쌓는 값
전에는 문제가 생기면 다음 날 access_log 와 애플리케이션 로그를 열어 봤다. 새벽에 생긴 문제를 아침에 알게 되면 그 몇 시간 동안 계속 문제가 있는 것이다.
그래서 사후에 찾는 대신 값을 계속 기록해 두는 쪽으로 바꿨다.
요청 수 · 응답 시간 · 오류 수 → 주기적으로 저장 → 그래프
grep 으로 로그를 뒤지는 것이 아니라 요청 수 와 오류 수 그래프에서 튀는 지점을 먼저 찾는 순서가 됐다.
로그는 그 시점을 알고 나서 해당 구간만 들여다보는 용도가 됐다. 어디를 볼지 정하고 나서 보는 것과 아무 데나 뒤지는 것은 걸리는 시간이 아주 달랐다.
대응 — 알림 기준을 다시 잡기
기준을 정해 두고 넘으면 메신저로 알리게 했는데 처음에는 실패했다. 기준을 너무 낮게 잡아서 알림이 계속 왔고 며칠 지나니 아무도 안 보게 됐다.
자주 오는 알림은 알림이 아니라 배경 소음이어서 기준을 다시 잡았다.
1. 지금까지의 값으로 평소 범위를 안다
2. 그 범위를 확실히 넘는 값으로 기준을 잡는다
3. 알림이 오면 매번 원인을 찾는다
마지막 항목이 기준 자체가 맞는지를 재는 자 노릇을 한다. 원인을 못 찾는 알림이 나오기 시작하면 그 기준이 잘못 잡혀 있다는 뜻이다.
주의 — 시간을 다루는 자리
값이 시각에 따라 쌓이는 구조가 되니 시간 문제가 계속 나왔다. 서버마다 시계가 몇 초씩 달라서 순서가 중요한 자료에서 순서가 어긋났다.
ntpd 로 시계를 맞추는 것부터 해서 그 몇 초 차이를 먼저 없앴다.
시간대를 어느 층에서 바꿀지도 정해야 했다. 저장은 하나로 통일하고 화면에 보여 줄 때만 바꾸는 쪽으로 정했는데 그 전에는 여기저기서 바꾸고 있어서 값이 어긋났다.
지금이 언제인지를 어디서 정하느냐도 문제였다. 한 처리 안에서 NOW() 를 여러 번 부르면 그때마다 다른 값이 나와서 지금은 시작할 때 한 번 잡아 그것을 끝까지 쓴다.
여기까지는 답을 낸 것이고 아직 못 낸 것도 남아 있다.
밤에 문제가 생기면 누가 보나
어디까지 자동으로 복구하게 할 것인가
되돌리기를 자동으로 할 수 있나
당번은 팀이 작아 부담이 크고 자동 재시작은 원인을 못 보고 넘어갈 것 같아 아직 안 걸어 뒀다. 되돌리기도 어떤 값이 어떻게 되면 되돌린다는 기준을 못 정해 사람이 보고 판단한다.
정리
- 24시간 도는 시스템은 내릴 시간이 없다
- 내리지 않고 바꾸는 방법이 필요하다
- 두 버전이 동시에 떠 있는 시간이 반드시 생긴다
- 컬럼 추가는 괜찮지만 이름 변경과
DROP COLUMN은 옛 버전을 깬다 DB변경을 세 단계로 나눈다DB가 이미 바뀌었으면 코드만 되돌려도 못 돌아간다- 로그를 뒤지지 말고 값을 계속 기록해 그래프로 본다
- 로그는 시점을 알고 나서 그 구간만 본다
- 자주 오는 알림은 알림이 아니다
- 알림이 오면 매번 원인을 찾을 수 있어야 기준이 맞는 것이다
- 서버 시계를 맞추고 시간대는 저장을 하나로 통일한다
- 한 처리 안에서 현재 시각은 한 번만 잡는다