아무도 기다리지 않도록 더 큰 워크스페이스로 옮기기
Mythex의 모든 프로젝트에는 자체 워크스페이스가 있습니다. 에이전트가 코드를 쓰고 앱의 미리보기가 실행되는 작은 클라우드 컴퓨터입니다. 새 워크스페이스의 메모리를 1GB에서 2GB로 올렸지만, 기존 워크스페이스는 1GB에 머물러 있었습니다. 확인한 날 기준으로 약 4분의 1이었습니다. 첫 번째 수정은 다음에 프로젝트를 열 때 더 큰 워크스페이스로 옮기는 방식이었습니다. 운영에 배포된 첫날, 이 방식은 한 사람을 7분 동안 기다리게 만들었습니다. 그래서 시간 제한을 엄격히 걸었고, 결국 프로젝트를 여는 과정에서 이동 작업 자체를 빼냈습니다.
기존 워크스페이스가 작은 채로 남은 이유
샌드박스 제공업체는 워크스페이스가 생성될 때 크기를 정하고, 일시 정지와 재개를 거쳐도 그 크기를 유지합니다. 템플릿, 즉 새 워크스페이스를 만드는 레시피를 바꾸면 그 변경은 바뀐 이후에 생성되는 워크스페이스에만 적용됩니다. 이미 있는 워크스페이스의 크기를 바꾸는 것은 없습니다.
이 점이 문제였습니다. 작은 워크스페이스 중 하나는 미리보기가 시작되는 동안 git push를 하다가 메모리가 부족해졌고, 11분 동안 응답하지 않았습니다. 그 때문에 게시가 실패했습니다.
첫 번째 시도: 깨어날 때 프로젝트 옮기기
워크스페이스는 아무도 사용하지 않으면 일시 정지되고, 프로젝트를 열면 깨어납니다. 깨어나는 순간이 프로젝트를 옮기기에 적당해 보였습니다. 아직 아무도 그 안에서 작업하고 있지 않기 때문입니다.
이동은 다음과 같이 진행되었습니다.
- 크기를 확인합니다. 워크스페이스가 2GB보다 작으면 옮깁니다. 크기를 알 수 없으면 아무것도 하지 않습니다.
- 게시를 방해하지 않습니다. 게시 작업은 워크스페이스의 파일을 읽으므로, 게시가 실행 중이면 이동을 건너뜁니다.
- 프로젝트를 패키징합니다. 프로젝트의 모든 것을 압축하며, 여기에는 git 히스토리(프로젝트가 가진 모든 체크포인트)와 소유자의 앱
.env파일이 포함됩니다. 대신 설치된 의존성(node_modules)은 제외하는데, 이는 나중에 다시 설치할 수 있기 때문입니다. - 바로 옮깁니다. 압축 파일을 옛 워크스페이스에서 새 2GB 워크스페이스로 스트리밍합니다. 그래서 파일 전체가 우리 서버의 메모리에 들어갈 필요가 없습니다.
- 전환하기 전에 비교합니다. 두 워크스페이스에서 파일 수, 최신 체크포인트, 체크포인트 수를 세어 봅니다. 세 가지가 모두 일치할 때만 전환합니다.
- 실패하면 옛 워크스페이스를 유지합니다. 어떤 오류나 불일치가 있으면 새 워크스페이스를 버리고, 이전과 같이 옛 워크스페이스에서 프로젝트를 엽니다.
비교 과정의 한 가지 세부 사항이 생각보다 중요했습니다. 이 검사는 관리자 계정으로 실행되는데, git은 다른 사용자가 소유한 저장소를 읽으려 하지 않습니다. 그래서 양쪽 모두 아무것도 출력하지 않았고, "아무것도 없음"이 "아무것도 없음"과 일치하면서 검사는 히스토리를 전혀 비교하지 않고 통과해 버렸습니다. 그 디렉터리를 신뢰하도록 git에 설정했고, 같은 실수가 다시 들어오지 않도록 테스트를 추가했습니다.
운영 첫날 무슨 일이 있었나
운영에 배포된 첫날, 한 프로젝트를 패키징하는 중에 깨어나는 과정 안에서 5분짜리 명령 시간 제한에 걸렸습니다. 소유자는 워크스페이스가 열리기까지 7분을 기다렸습니다. 그리고 이동이 실패했기 때문에 프로젝트는 여전히 작은 상태였습니다. 다음번에 열면 이동을 다시 시도하면서 또 기다리게 만들었을 것입니다.
자기 프로젝트를 여는 동안 사람을 기다리게 하는 마이그레이션은 나쁜 거래입니다. 깨어날 때 이동을 하겠다는 것은 아무도 눈치채지 못하게 하려는 의도였습니다.
두 번째 시도: 엄격한 예산
같은 날 네 가지를 바꾸었습니다.
- 이동 전체에 1분. 크기 확인, 패키징, 새 워크스페이스 생성, 복사, 압축 풀기, 비교 등 모든 단계가 60초의 예산을 함께 씁니다. 예산이 다 되면 프로젝트는 옛 워크스페이스에서 열립니다.
- 대기뿐 아니라 작업도 멈춥니다. 우리 쪽에서 포기하는 것만으로는 충분하지 않습니다. 소유자가 곧 사용할 워크스페이스 안에서 압축 작업이 계속 돌고 있을 수 있기 때문입니다. 이제 각 압축 명령은 예산이 끝나기 직전에 워크스페이스 안에서 강제 종료됩니다. 우리가 포기한 뒤에 새 워크스페이스가 도착하면 그것은 버려집니다.
- 소유자를 정리 작업으로 기다리게 하지 않습니다. 임시 압축 파일을 삭제하는 작업은 이제 백그라운드에서 실행됩니다.
- 열 때마다 다시 시도하지 않습니다. 옮기지 못한 프로젝트는 24시간 동안 그대로 두어, 실패가 열 때마다가 아니라 하루에 한 번의 지연만 발생하도록 합니다.
세 번째 시도: 깨어나는 과정에서 빼내기
이제 최악의 경우는 1분이 되었습니다. 하지만 1분도 여전히 1분이고, 이동이 누군가의 경로 위에 있을 필요가 전혀 없다는 것을 깨달았습니다.
이제 1GB 워크스페이스는 더 이상 만들어지지 않습니다. 그래서 이것은 계속 진행되는 과정이 아니라, 고정된 워크스페이스 목록에 대한 일회성 작업입니다. 깨어나는 과정 안에 넣어 두었기 때문에, 느린 이동 하나하나의 대가를 실제 사람이 치러야 했고, 워크스페이스가 옮겨지지 않는다는 사실은 누군가 방금 기다린 뒤에야 알 수 있었습니다.
그래서 깨어나는 과정에서 이동을 완전히 빼냈습니다. 프로젝트를 여는 일은 이전과 똑같이 동작합니다. 남아 있는 작은 워크스페이스는 감독되는 배치 작업으로 처리합니다. 아무도 기다리지 않으며, 옮겨지지 않은 워크스페이스는 배치 보고서에 나타나고, 우리는 그곳에서 그것을 살펴볼 수 있습니다. 소유자 앞에서 드러나지 않습니다.
얻은 교훈
- 크기 조정이 항상 가능한 것은 아닙니다. 플랫폼이 생성 시점에 크기를 고정하면, 기본값을 올리는 것은 새로 만드는 것에만 도움이 됩니다. 오래된 것들을 위한 계획도 세워야 합니다.
- "아직 아무도 사용하지 않는다"는 것이 곧 누군가 기다리고 있다는 뜻은 아닙니다. 제품으로 들어가는 길목에서 하는 작업은 사람이 지켜보는 작업입니다.
- 사용자의 경로에 있는 모든 것에는 예산을 두고, 예산이 다 되면 작업을 멈추세요. 우리 쪽에서만 시간 초과로 끝내고 다른 곳에서 명령이 계속 돌아가게 두면 문제는 그대로 남아 있을 뿐입니다.
- 일회성 마이그레이션은 일회성 작업에 두세요. 일상적인 행동 안에 숨겨 두면 작성하기는 쉽지만 운영하는 비용은 더 커집니다.
- 안전 점검도 테스트하세요. 아무것도 비교하지 않는 비교는, 실제로 비교해서 통과한 것과 똑같아 보입니다.
Mythex에서 무언가를 만들고 있다면 할 일은 없습니다. 목표는 메모리가 부족해 실행되지 않는 워크스페이스를 줄이는 것이고, 프로젝트를 여는 속도는 이전과 같게 유지하는 것입니다. 워크스페이스가 일시 정지되고 깨어나는 방식은 docs의 비공개 워크스페이스에서 다룹니다. 메모리 부족 이야기가 더 있다면 진행률 표시줄 속에 숨은 메모리 부족 크래시를 참고하세요.