액티브펍 네트워크의 부하 내구성 문제

몇 주 전에 짧은 휴가를 다녀왔습니다. 원래는 좀 더 일찍 가서 사람들이 조금이라도 더 적을 때를 원했지만 회사 일정 상 그럴 수는 없었습니다. 그래서 결국 성수기의 시작을 알리는 시점에 집과 회사에서 최대한 멀리 떨어진 장소로 출발했는데 그나마 성수기의 시작이었지만 소위 극성수기에는 해당하지 않는 날짜라는 점에 위안을 삼았습니다. 숙소의 방 배정 시작 시각 때문에 아침 일찍 출발해야 했는데 너무 늦게 도착하면 원하는 옵션에 맞는 방을 배정 받을 수 없을 가능성이 있었기 때문입니다. 새벽에 남쪽으로 고속도로를 타러 내려가다가 그 시간에 문을 연 드라이브스루 커피 매장에 들렀는데 아직 드라이브스루가 오픈하기 전이어서 주차장에 차를 세우고 매장에 들어가 커피를 주문한 다음 문득 뒤를 돌아 유리창 바깥을 보니 아침 운동을 마친 것 같은 사람들이 진짜 좀비 처럼 비척비척 주차장을 가로질러 걸어 오고 있어 잠깐 무서웠습니다.

한국에서 평생을 일하는 여느 노동자처럼 긴 휴가 같은 걸 다녀올 수는 없었지만 나름 휴가는 나쁘지 않았습니다. 일단 집과 회사에서 물리적으로 멀면 멀수록 실질적으로 집과 회사에 대한 생각을 훨씬 덜 할 수 있습니다. 개인적으로는 장거리 자전거나 등대 스탬프 투어 같은 다른 마이크로 어드벤처를 좋아하기도 하지만 시간이 지나고 보니 휴가 때 마이크로 어드벤처 보다는 정말로 ‘휴가’의 의미에 가까운 휴식이 필요하다는 점을 알게 됐는데 더 어릴 때는 휴양 시설에서 어떻게 놀아야 할 지 전혀 알 수 없어 전전긍긍하고 또 심심해 견딜 수 없었지만 이제는 그런 시설에 좀 더 익숙해져 ‘휴가’를 보낼 수 있게 된 것 같습니다. 여느 서양 사람들처럼 좀 더 긴 기간을 들여 재충전할 수 없기는 하지만 뭐 그럴 돈도 없고 시간도 없으며 여느 한국인들처럼 뭐든 빨리 해결하는 생활 습관의 연장으로 휴식 역시 빨리 해치운다고 생각하니 뭐 지구 상에 더 느긋한 휴가를 갈 수 있는 사람들이 있음을 알고 있지만 그리 나쁘지 않았습니다.

그건 그렇고 휴가를 마무리하고 다시 돌아가기 전날 저녁 숙소에서 침대에 앉아 폰을 쳐다보는데 문득 마스토돈 타임라인이 실시간보다 느리다는 점을 발견했습니다. 처음 발견했을 때는 한 시간 정도 느렸는데 그런가보다 하고 다른 일을 하다가 다시 보니 실시간과의 시간 차이는 점점 벌어져 어느 새 여섯 시간이 되고 또 아홉 시간에 도달합니다. 가령 현재 시각이 오전 9시라면 페더레이션 타임라인은 9시간 전인 같은 날 0시에 머물러 있고 이 상태에서 새로고침을 해도 실시간은 오전 9시의 게시물이 로딩 되지 않는 상태였습니다. 로컬 타임라인이나 팔로잉 타임라인은 영향을 받지 않아 당장 마스토돈을 사용하는 데는 지장이 없었지만 페더레이션 타임라인이 계속해서 실시간과 9시간의 시간차이를 유지하자 휴가 마지막 날 밤에 왜 이런 현상이 일어나는지 곰곰히 생각해 보기 시작합니다.

여느 마스토돈 서버와 달리 개인적으로 운영하는 마스토돈 서버는 직접 서버를 구축하고 운영하는 대신 완전관리되는 서비스를 통해 운영하고 있는데 서버를 직접 구축하고 관리할 기술이 없었기 때문입니다. 온라인에 널리 공유되는 튜토리얼 문서를 참고하면 불가능하지 않겠지만 혼자 사용하는 서비스라면 그러다가 하는 실수를 용납할 수 있지만 저 말고 다른 분들이 함께 사용하는 서비스에 그럴 수는 없었습니다. 웹 기술을 잘 모르는 사람 입장에서 마스토돈은 이전에 구축해 본 여느 블로그 도구나 위키 도구, 혹은 모니터링 도구에 비해 훨씬 더 다양한 기술 스택과 환경을 요구했는데 이들 모두를 잘 관리할 자신이 없었습니다. 또 장애나 재해가 발생할 때 원인을 파악해 빠르게 대응할 수 있을 것 같지도 않았는데 만약 장애나 재해가 발생할 때 본업이 바쁘다면 이도 저도 아닌 최악의 상황으로 치달을 것이 분명했습니다.

그래서 어른의 친구 신용카드를 사용해 완전관리 서비스를 통해 서버를 열고 아무 걱정 없이 서버를 그저 사용하고만 있습니다. 이 글을 쓰는 2023년 여름 현재 마스토돈 새 버전이 나왔는데 다른 서버 관리자님들이 적용 시점을 고민하고 있을 때 이미 제가 잠 자는 사이에 서비스 관리자가 수정사항을 검토하고 테스트한 다음 적용을 완료한 상태입니다.

한편 페더레이션 타임라인이 실시간으로부터 계속해서 9시간 느린 상태가 되자 완전관리 서비스를 사용하는 서버의 문제점이 바로 노출됐는데 스스로는 현재 상황이나 원인, 문제 해결 방법을 전혀 알 수 없었다는 점입니다. 일반 사용자, 마스토돈 사이트 관리자가 볼 수 있는 화면 말고는 추가 정보를 얻을 수 없었기 때문에 이 문제가 왜 일어나는지 전혀 알 수가 없었는데 만약 서버를 직접 구축했다면 힌트를 얻을 만한 다양한 정보에 접근할 수 있었겠지만 완전관리되는 서비스에서는 그럴 수가 없었습니다. 심지어 온갖 생각을 거듭하다가 실시간과 딱 9시간 차이가 유지되는 것을 보고 혹시 협정세계표준시와 한국표준시 사이의 차이로부터 비롯한 문제가 아닐까 의심해 보기도 했습니다. 그러다가 문득 관리자 화면에서 마스토돈의 메시지 큐를 열어보니 릴레이에 의해 연결된 네트워크 상에 메시지가 대량으로 유입되었고 완전관리 서비스에 사용하는 요금제 상 처리량에 제한이 있어 실시간으로 쏟아지는 메시지는 큐에 쌓여 처리되는데 9시간의 딜레이가 발생하고 있는 상황을 파악합니다.

집으로 돌아오는 차 안에서 살펴보니 이미 다른 서버 관리자님들은 서버 사양을 증설하거나 메시지 처리방식을 최적화해 대응하고 있었는데 일단 운전석 옆자리에서 손에 아이폰 하나만 덜렁 든 상태로는 완전관리되는 서비스이건 아니건 뭔가 조치를 취하기 쉽지 않은 상황이었습니다. 하지만 또 한편으로는 상황을 모니터링하고 자원을 추가 투입할지 여부를 결정하는 정도는 할 수 있었는데 약 30분 정도 관찰하는 동안 계속해서 메시지 큐에서 메시지가 처리되는데 약 9시간 정도 딜레이가 유지되는 것을 보고 이대로 모니터링만 하는 건 서버 사용자분들께 예의가 아니다 싶어 일단 공지를 내고 조치를 취하기 시작합니다. 사실 완전관리형 서비스를 사용하는 입장에서 이 상황에 대응하는 방법은 서버를 직접 관리하시는 분들의 대응과 별로 다르지 않은데 결과는 비슷하지만 방법은 약간 다릅니다. 서버 관리자분들은 VPS 사양을 늘리거나 메시지 큐를 최적화해 대응하시고 저는 완전관리 서비스의 상위 상품을 구입해 처리량을 늘립니다. 과정은 서로 상당히 다르지만 결과는 비슷하고 또 과정에 사용하는 방법의 일부가 신용카드인 점은 비슷합니다.

하지만 처리량을 늘려도 메시지 처리에 걸리는 딜레이가 줄어들어 서서히 실시간에 가까워지고는 있었지만 여전히 드라마틱하게 개선되지는 않았고 시간이 흐름에 따라 오히려 딜레이가 늘어나기도 하고 있었습니다. 이제 슬슬 이 상황의 원인을 알아보니 트위터가 모든 고객들의 단위시간 당 사용량을 제한하기 시작했고 평소 타임라인을 잡아당기는데 중독된 저와 비슷한 중독자들이 새로운 중독처를 찾아 마스토돈 네트워크로 대거 이동했으며 이 분들이 쏟아내는 메시지가 같은 릴레이를 공유하는 모든 서버들로 흘러 넘치고 있었던 것이었습니다. 이전에 마스토돈 커뮤니티는 오래 못 갈 거라고 봐요를 통해 이야기했듯 액티비티펍 네트워크에서 타임라인을 잡았당겼다 놓는 중독 행위에 보상을 받으며 살아가고 있지만 이 네트워크가 그리 오래 두지되지는 않을 거라고 생각하는 입장이어서 이 상황이 그리 오래 가지 않으리라고 생각했습니다.

그래서 이 상황에 실시간 페더레이션 타임라인을 따라가기 위해 더 많은 자원을 투입하는 것은 좋은 선택이 아니라고 판단합니다. 일단 비용을 들여 시간 당 메시지 처리속도를 늘렸지만 여전히 실시간에 근접하는 속도는 느렸는데 그렇다고 이 상태를 더 따라갈 생각도 없었습니다. 하지만 계속해서 무한히 메시지가 쌓이게 두면 로컬 타임라인이나 사용자들 각각의 팔로잉 타임라인에 문제를 일으킬 수 있었으므로 조치를 취하기는 해야 했는데 간단히 일시적으로 릴레이를 비활성화 했습니다. 여전히 자동차가 집으로 향하는 동안 메시지 큐에 메시지가 쌓이는 속도에 비해 메시지가 처리되는 속도가 더 빨라지기 시작했고 시간이 지나자 메시지 큐에 드디어 더 이상 남아있는 메시지가 없는 상태가 됐습니다. 하지만 페더레이션 타임라인은 고요 그 자체가 되었고 마치 마스토돈 서버는 온 지구상에 오직 이 마스토돈 서버 하나만 남은 것 같은 상태가 됩니다. 여전히 팔로잉 타임라인 기준으로는 다른 서버 사용자들과 문제 없이 메시지를 주고 받을 수 있었지만 페더레이션 타임라인을 보면 더 이상 마스토돈에는 그 누구도 남아 있지 않은 기괴한 모습이었습니다.

한편 긴 시간을 이동해 집에 돌아와 짐을 풀고 바닥에 누워 다시 폰을 쳐다보며 이번에는 다른 서버 관리자 분들의 행동을 모니터링 했는데 어떤 대형 서버 관리자님은 그 서버가 릴레이에 연결된 모든 서버에 커다란 부하를 주고 있다고 판단해 릴레이를 비활성화 시켰습니다. 또 다른 서버는 신규 가입을 중단하기도 했는데 지금까지 살펴본 이 상황의 원인을 생각하면 문제는 네트워크 전체 사용량의 문제이기 때문에 서버 각각이 가입자를 받지 않는다고 해서 해결될 문제 처럼 보이지 않았습니다. 그래서 가입은 막지 않고 그냥 놔뒀고 예상 대로 아무 문제도 없었습니다. 한 서버에서 가입을 받지 않아도 이 서버가 연결된 릴레이 상의 다른 서버가 가입자를 받으면 가입을 받지 않는 조치는 아무런 도움이 되지 않습니다. 한편 예상 대로 액티비티펍 네트워크에 새로 유입된 사용자들 거의 대부분은 약 48시간 정도 액티브펍 네트워크에 강한 부하를 일으킨 다음 빠져나갔는데 습관은 그리 쉽게 바꿀 수 있지 않기 때문입니다.

이쯤 되니 조용히 비활성화했던 릴레이를 원래대로 돌려놓고 다시 좀 더 모니터링 했는데 잠깐씩 메시지가 처리되는데 10분 이내의 딜레이가 발생하기도 했지만 대부분 문제가 일어나지 않았고 페더레이션 타임라인은 대부분 실시간 상태를 유지했습니다. 그래서 늘렸던 서버 처리량을 조용히 원래대로 되돌려 놓으려 했는데 잠깐 동안에 스토리지 사용량이 급격히 늘어나 바로 완전관리 서비스 상품을 원래대로 되돌릴 수는 없었습니다. 그래서 잠깐 이대로 두고 컨텐츠 리텐션 설정에 따라 캐시 스토리지 사용량이 줄어드는 시점에 맞춰 상품을 원래 사용하던 처리량 수준으로 되돌릴 작정입니다.

이렇게 약 3일 간에 걸친 액티비티펍 네트워크의 대규모 부하 유입 에피소드는 적어도 제 관점에서는 마무리 됐고 덕분에 휴가를 마치고 돌아오는 차 안에서 서비스를 모니터링하고 메시지 큐를 살펴보고 다른 서버 관리자님들의 행동을 살펴보고 페더레이션 타임라인에 새로 유입된 사용자분들의 행동을 살펴보며 긴 이동 시간이 길지 않게 느껴지는 장점도 있었습니다.

한편 이전에 마스토돈의 계정 이동성에 대한 걱정 같은 걸 한 적도 있는데 액티비티펍 네트워크는 사용 기간이 길어질 수록 이 네트워크가 장기적으로 유지되기에 충분히 단단하게 설계되지는 않은 것 같다는 느낌을 받곤 합니다. 이번 에피소드를 통해 느낀 가장 큰 당황스러움은 액티비티펍 호환 서버들끼리 패시브 상태로 통신하기 위해서는 릴레이 서버가 연동되어 있어야 합니다. 액티비티펍 호환 서버들은 사용자가 직접 다른 서버 사용자를 팔로우 하는 식의 액티브 통신에는 릴레이 같은 매개가 필요하지 않지만 다른 서버의 다른 사용자를 탐색하기는 굉장히 불편하고 또 사실상 이런 탐색이 어렵습니다. 그래서 릴레이 서버를 통해 패시브한 연결 상태를 유지해 같은 릴레이로 연결된 사용자들을 페더레이션 타임라인을 통해 탐색하고 발견할 수 있게 하면 서버 사용자들의 편안한 사용을 도울 수 있습니다.

그런데 이 릴레이는 근본적으로 릴레이에 연결된 모든 서버는 릴레이에 유입되는 전체 메시지를 처리할 수 있는 사양을 갖추고 있어야만 합니다. 릴레이는 사실상 여기에 연결된 모든 서버로부터 작성되는 모든 공개 글을 네트워크에 쏟아 붓고 있어 릴레이에 연결된 아무리 작은 서버도 네트워크 전체의 메시지를 처리할 사양을 보유해야만 페더레이션 타임라인을 통한 패시브한 연결을 유지할 수 있습니다. 만약 어느 서버 하나가 네트워크 전체 메시지량을 처리하기에 사양이 부족하면 이번 처럼 페더레이션 타임라인 처리속도가 느려져 서버 사용자분들께 불편을 끼칠 수 있습니다.

그런데 근본적으로 릴레이에 연결되어 있더라도 네트워크 전체의 메시지량에 모든 서버가 대응해야 하는 점은 프로토콜의 설계 결함이 아닐까 싶은 생각이 들었습니다. 태초에 액티비티펍 프로토콜이 어떤 철학에 기반해 설계되었을지는 잘 모르겠지만 적어도 제가 경험하는 한국어 사용자 권역의 액티비티펍 네트워크는 사용자가 아주 많은 대규모 서버와 사용자가 아주 적은 소규모 서버들이 다양하게 같은 릴레이에 묶여 동작하고 있습니다. 이런 상황에서 릴레이에 메시지가 대규모로 유입되면 소규모 서버들은 위에서 소개한 문제를 겪을 수밖에 없는데 그저 각 서버의 모든 메시지를 대책 없이 릴레이를 통해 네트워크에 연결된 모든 서버에게 들이 붓는 건 마치 DDoS와 비슷한 동작처럼 느껴집니다.

만약 액티비티펍 프로토콜이 좀 더 이런 일시적인 대규모 부하에 내구성을 가진 모양으로 설계됐다면 메시지가 서버를 떠나 릴레이에 도달하기 전에 각 서버에서 먼저 릴레이에 우선 전달할 메시지와 좀 나중에 전달할 메시지를 구분하는 적당한 규칙에 의해 어떤 서버에 대규모 부하가 일어나더라도 릴레이를 통해 이를 실시간으로 네트워크에 연결된 모든 서버로 전달하는 동작을 그대로 두지는 않았을 겁니다.

하지만 실제로는 릴레이 서버가 평소에는 각 서버의 패시브 연결을 유지해 사용자들의 편안한 탐색을 도왔지만 대규모 부하 상황에서는 한 서버의 부하를 모든 서버로 똑같이 전파하는 역할을 했고 덕분에 저 자신을 포함한 소규모 서버 관리자들이 한동안 골머리를 앓게 만들었습니다. 어떤 릴레이 운영자님들은 릴레이 코드를 수정해 통계적으로 릴레이에 유입되는 트래픽 중 일정 비율만 네트워크에 전파되도록 하는 시도를 하고 계신 것 같았는데 단기적으로는 센스 있는 재미있는 접근이지만 장기적으로는 릴레이를 포함한 액티비티펍 프로토콜의 설계 자체가 이런 상황에 대비하고 또 실제 구현에 반영되어야만 할 거라고 봅니다.

여튼 이제 트위터로부터 잠깐 넘어왔던 대규모 트래픽은 다시 트위터로 돌아갔고 액티비티펍 네트워크는 다시 평화로워졌으며 조만간 컨텐츠 리텐션에 의해 캐시 스토리지 크기가 줄어들면 한 달에 부담하는 완전관리 서비스 사용 요금도 줄어들어 다시 처음에 생각한 아주 낮은 비용으로 일론님의 기분 변화에 별 영향을 받지 않는 아무말 인프라를 유지하는 목표로 돌아갈 수 있을 것 같아 보입니다. 액티비티펍 네트워크의 부하 내구성은 조금 실망스러웠고 또 한편 이 글을 작성하는 현재 최근에 겪은 결함 내구성 문제에 대한 에피소드도 있는데 그건 다른 기회에 소개하겠습니다.

한편 자외선을 직접 받으면 몸에 아주 많은 문제가 생겨 함부로 야외 활동을 하는데 준비 절차가 많아 물놀이를 피하곤 했는데 이번 휴가 기간 동안에는 날씨가 아주 흐린 날이 계속된 덕분에 야외 물놀이를 안전하게 할 수 있어서 좋았습니다.