인스턴스 성능 개선 (메가토픽, 데이터베이스 크기 및 극단적 부하)

감사합니다. 아마도 디버깅과 시행착오로 인해 수 시간의 시간을 절약해 주셨을 것입니다.

이 동작의 차이는 프론트엔드 관련 문제(프론트엔드는 제 전문 분야가 아니라서, 백엔드와는 대조적으로)가 앱을 "크래시"시키는 것으로부터 비롯된 어떤 애플리케이션적 상관관계라는 결론에 도달하게 했습니다. 그리고 사람들이 특정 주제에 머물러 1분에 수십 개의 메시지가 쌓이는 동안 "자동 업데이트"를 기다리는 상황에서 발생하는 작업들 때문입니다.

이 메가 문장을 요약하자면: 빠른 실시간 토론의 “막힘” 현상이 프론트엔드 문제라는 것이 당신의 결론인가요?

저희 분석은 멀리까지 진행되지 않았지만, CPU 부하가 최대치에 근접하지 않고 약 25% 수준에 머물러 있다는 것을 관찰했습니다. 지난 몇 년간 CPU 100%에 도달한 경우가 여러 번 있었지만, 지난 토요일의 최신 사고에서는 그렇지 않았습니다. 동시 접속 사용자가 약 150명 정도였을 뿐입니다.

백엔드를 의심하게 된 이유는, 저희가 이러한 게임 채팅을 수년간 운영해 왔음에도 불구하고 이 “막힘” 현상을 이전에 본 적이 없기 때문입니다. 지난 몇 년간 데이터베이스가 성장하여 현재 800,000개 이상의 게시물이 있습니다.

이 현상을 처음 목격한 시점은 언제인가요? 최신 메이저 업데이트와 관련된 회귀 문제(regression)일 수 있을까요? 봄에는 사이트와 성능이 모두 정상이었으며, 여름 동안 사용자 수가 크게 증가하지도 않았습니다.

Babel은 매우 비효율적인 플러그인입니다. 따라서 Babel을 사용 중이라면 문제가 생길 가능성이 높습니다 .. 특히 동시에 활동하는 사용자 부하가 많은 경우 더욱 그렇습니다.

현재 1,000명이 같은 주제를 보고 있는 상태에서 한 명이 게시물을 작성할 때의 성능을 개선하기 위한 작업을 백로그에 TODO로 등록해 두었습니다.

현재 설계 방식으로는 1,000명 모두에게 "새로운 게시물이 있습니다"라는 알림을 먼저 보낸 후, 1,000명이 모두(대부분 동시에) 서버로 접속하여 "요청한 이 새로운 게시물이 무엇인가요?"라고 묻게 됩니다.

클라이언트가 서버를 과도하게 압박하지 않도록, 이 문제를 더 깔끔한 방식으로 최소한 레이트 리미팅을 적용할 예정입니다. 또한 이러한 예외적인 상황을 위해 수행할 수 있는 최적화 작업이 여러 가지 있습니다.

이 문제가 이미 인지되고 있다는 소식은 정말 좋습니다. 지난 봄 이후로 이 문제가 재발했는지 확인해 주실 수 있을까요?

우리 지역 아이스하키 리그는 10월 1일에 시즌을 시작합니다. 따라서 매주 게임이 시작될 때 웹사이트에 실시간 트래픽 스파이크가 발생할 수 있습니다. 만약 실제(비시뮬레이션) 환경에서 해당 동작을 관찰하고 싶으시다면, 이를 연구하시는 데 활용할 수 있을 것입니다.

관심 있으시면 DM을 남겨주세요. 기꺼이 지원하겠습니다.

UX 관점에서 보면, 시스템이 과부하로 어려움을 겪기 시작하더라도 사용자가 토론이 활성 상태임을 어렴풋이 인지할 수 있어야 합니다. 이를 통해 불필요한 브라우저 새로고침을 방지할 수 있을 것입니다.

아니요, 안타깝게도 그 사실을 확인해 드릴 수 없습니다. 처음부터 계속 그런 상태였습니다.

첫 번째 게임이 방금 종료되었고, 3월에는 없었던 문제가 분명히 발생했습니다. 원인은 아직 파악되지 않았습니다.

서버 부하가 100%에 훨씬 못 미치는데도 프론트엔드에서 게임 채팅이 먹통이 됩니다.

우리 사용자 중 한 명인 Ole가 먹통 현상 동안 429 서버 응답이 여러 건 발생했음을 발견했지만, 게임 중에 이러한 점검을 해본 적이 없어 이것이 “정상적인” 것인지 여부는 말씀드리기 어렵습니다.

@iceman 님, 해당 사이트에서도 이런 현상을 확인해 보셨나요?

전혀 무관한 ‘500’ 오류를 조사하던 중 그 중 하나를 확인했습니다 :sweat_smile:
서버는 전혀 바쁘지 않았지만, 프론트 엔드 nginx 설정(http2)을 건드리고 있었기 때문입니다.

"게임 채팅"이라 함은 "동시에 동일한 주제에서 활동하는 많은 수의 사용자"를 의미하시나요?

실제로, 몇 시간 동안 약 900개의 반동적인(반발적인) 답변이 올라왔습니다. @ljpp는 더 정확한 사용자 수를 가지고 있지만, 경기 중 언제든지 수백 명의 사용자가 해당 주제를 보고 있다는 뜻입니다.

이상하게도, 이 문제는 모든 사용자에게 영향을 미치지 않습니다. 예를 들어, 저는 어떤 기기에서도 문제를 경험하지 않았습니다. 하지만 보고에 따르면 상당히 광범위한 문제인 것 같습니다.

주의를 기울이지 않으면 알아차리기 쉽지 않습니다.

처음에는 30~60초 동안 답변이 없는 상태가 지속됩니다. 아무것도 “잘못된” 것처럼 보이지 않고, 그저 조용할 뿐입니다. 이 기간 동안 본인이 직접 게시글을 작성할 수도 있습니다. 그러다 갑자기 순식간에 수십 개의 메시지가 도착하면서 뒤처져 있었음을 깨닫게 됩니다. iOS Safari와 Android Chrome에서 이 현상을 목격했습니다.

실시간 게임 채팅은 활발하지만 극단적인 수준은 아닙니다. 어제 약 3시간 동안 총 972개의 메시지가 전송되었습니다.

Otteluseuranta: Lukko - Tappara 2.10.2020 - Liveseuranta - Tappara.co

다음 게임 채팅은 오늘 14:00 UTC에 열립니다. 팬데믹 상황 때문에 홈 경기임에도 비슷한 수치를 예상합니다.

@pfaffman님의 게시물에 동의합니다.

포럼 플랫폼에 채팅 사용 사례를 억지로 적용하려는 건 아닌가요?

대신 Mattermost나 Discord 같은 채팅 서비스를 Discourse 사이트의 UI에 통합하고, 이 매체를 통해 게임 내 토론을 다루는 건 어떨까요?

게임 전후 토론처럼 사용 부하가 덜하지만, 나중에 많은 사용자가 다시 보고 싶어 할 수 있는 유용한 요약 정보를 담을 수 있는 포럼 주제(Topic)로 게임을 다루는 다른 방법을 찾을 수도 있습니다.

또한, 즉흥적인 대량의 채팅을 포럼에 저장하는 데 어떤 이점이 있는지 모르겠습니다. 그걸 다시 읽을 사람이 있을까요? 유용할까요?

글쎄요, 그는 이 기능을 '채팅’이라고 부르지만, 해당 사용자의 말에 따르면 그의 Discourse 설정은 주제당 약 3시간 동안 972개의 게시물을 처리할 수 없다고 합니다. 제 생각에는 그렇게 되어야 하는데, 단순한 phpbb조차도 3시간 동안 이보다 몇 배는 더 많은 게시물을 처리할 수 있습니다.

10초마다 1개의 게시글을 올리라는 건가요? 그 자체만으로는 비합리적이지 않아 보입니다. 하지만 그 주제에 1000개의 게시글이 쌓이고, 수백 명의 사용자가 참여하며, 게시글이 집중적으로 올라오는 순간까지 겹친다면요. 그 어려움이 이해됩니다!

그렇다면 여기서 진정한 원인이나 병목 현상은 무엇일까요? 참여하는 사용자의 수일까요, 10초당 1개의 게시물 제한일까요, 아니면 변경된 콘텐츠를 (너무) 많은 비익명/익명 사용자에게 렌더링하는 것일까요? 아니면 수많은 로그인된 사용자에게 서비스를 제공하기 위해 필요한 연결 수일까요?

동일한 시간대에 같은 주제에서 동일한 양의 게시물을 작성하는 사용자가 단 2명뿐이라면 동일한 문제가 발생할까요?

단 972명의 로그인된 사용자가 해당 주제에서 게시물 1개씩만 작성해도 Discourse가 이를 처리하지 못할까요? 그렇다면 왜 그런가요? Discourse는 동시 로그인 사용자 수가 적은 아주 작은 커뮤니티에만 적합한 선택일까요?

우리는 때때로 최대 400명의 동시 로그인 사용자가 하루에 최대 3,000개의 게시물을 작성하고 있는데, 지금까지는 문제가 없었기 때문에 궁금할 뿐입니다.

서버 사양과 실행 중인 유니콘(프로세스) 수를 반드시 고려해야 합니다. 그렇지 않으면 이러한 스트레스 시나리오 결과는 그 의미가 떨어집니다.

Blenderartists(@bartv)는 64GB 서버에 유니콘이 약 12개 정도 실행 중인 것 같습니다. 꽤 거대한 구성이네요 :slight_smile:

네, 맞습니다. 현재 DO(DigitalOcean)에서 8GB RAM / 4 vCPU 환경으로 운영하고 있으며, 지금은 아무 문제가 없습니다. 따라서 이 문제의 해결책이 단순히 리소스(RAM과 CPU)를 늘리는 것이라면, 저는 괜찮습니다. Discourse로 재출시된 이후 피크 시간대에는 바이럴된 한 게시물에 약 2,000명의 동시 방문자가 몰렸을 때 로드 평균이 1을 약간 상회했고, CPU 사용률은 60~70%였습니다. 현재 약 200~250명의 동시 접속자가 로그인되어 있는 평균 상태에서는 CPU가 유휴 상태(bored)이며 사용률이 약 15~20% 수준입니다.

맞습니다 :slight_smile: 데이터를 공유하는 데 기꺼이 응하겠습니다. 다만 우리는 Discourse를 채팅으로 사용하지 않아서 그런 스파이크를 본 적이 없습니다.

이러한 주장을 할 수는 있지만, 대화를 두 개의 플랫폼으로 분리하는 아이디어는 정말로 꺼립니다. 실시간성은 실제로 Discourse의 핵심 기능 중 하나이며, 최종 사용자들도 이를 매우 높게 평가합니다. 우리의 게임 시간 대화는 큰 인기를 끌고 있으며 커뮤니티 문화의 중요한 부분입니다.

참고로 우리는 이러한 방식을 4년 동안 운영해 왔으며, 이는 우리가 직면한 새로운 문제입니다. 따라서 수백 번의 게임이 아무 문제 없이 진행되어 왔으며, 아무것도 “억지로” 적용한 적이 없습니다.

우리 커뮤니티의 경험 많은 멤버 중 한 명이 이론을 제시했습니다 – Discourse의 전역 한도에 도달하고 있는 것이거나, CloudFlare가 영향을 미치고 있는 것은 아닌지 궁금해합니다.

DISCOURSE_MAX_REQS_PER_IP_PER_MINUTE : IP당 분별 요청 수 (기본값은 200)

DISCOURSE_MAX_REQS_PER_IP_PER_10_SECONDS : IP당 10초별 요청 수 (기본값은 50)

다음 게임은 1시간 후에 있으며, CF 캐시를 비활성화한 상태로 시도해 볼 것입니다.

참고로 CloudFlare도 4년 동안 사용해 왔습니다. 여기서는 일반적으로 권장되지 않지만요. 그동안 문제점이 거의 없었으며, Brotli 문제가 하나 있었고, 업데이트되지 않은 템플릿 문제가 하나 있었습니다.

아니요, CF가 근본 원인이 아닙니다. 캐시를 비활성화한 상태로도 문제가 재현되었습니다. 429 오류가 보고되었습니다.

아이디어가 있는 분 있으신가요?

그 우려를 충분히 이해합니다. 채팅에서 사라진 흥미로운 통찰의 기록을 잃고 싶지 않거든요. 어려운 딜레마입니다.