Skip to main content
За кулисами
За кулисамиEngineeringDecisions

Как уследить за 4000 серверов Discord: Grafana, PostHog и что они нам показали

Цикл, который незаметно создавал половину нашего трафика, три миллиона бессмысленных запросов в день и атака, закончившаяся через минуту. Что видит наш мониторинг и чего он намеренно не видит.

Опубликовано автор AlphaCloud4 мин чтения

AlphaCloud работает чуть больше чем на 4000 серверах Discord, распределённых по четырём шардам. Это четыре процесса, каждый обслуживает часть серверов, и все они общаются с одним и тем же API.

При таком размере проблема редко проявляется тем, что что-то ломается. Гораздо чаще всё работает, просто дороже, медленнее или шумнее, чем должно. Поэтому в сентябре 2026 года мы перестроили наш мониторинг. Эта статья показывает, как он выглядит и что он показал нам в первые недели.

Два инструмента, два вопроса

Grafana отвечает на вопрос: что делает бот? Бот и API отправляют метрики в Prometheus (запросы, время ответа, доля ошибок, ответы Discord, использование ИИ), а логи уходят в Loki. У каждого серверного узла свой стек, а Grafana доступна только через частную сеть, не из интернета.

PostHog отвечает на вопрос: что люди видят на наших сайтах? Просмотры страниц, ошибки в браузере, время загрузки и, с согласия, записанные сессии. PostHog запускается только после того, как ты дашь согласие в баннере cookie.

Разделение намеренное. Grafana смотрит на машины, PostHog на интерфейсы. Если втиснуть оба в один инструмент, получишь либо пользовательские данные в серверных логах, либо нагрузку на серверы в продуктовой аналитике.

Что он нашёл

Цикл, который создавал половину трафика

Опросы со временем окончания закрывает фоновая задача, которая каждую минуту проверяет, не истекло ли что-нибудь. Она делала это для каждого сервера по отдельности. При примерно 1000 серверов на шард и четырёх шардах это давало около 70 запросов в секунду, и почти все они отвечали «ничего не истекло».

Мы заметили это только в Grafana, когда разбили запросы бота к API по путям: один этот эндпоинт составлял больше половины всего трафика. Всё работало. Просто система несла нагрузку, о которой никто не просил.

Теперь каждый шард раз в минуту спрашивает: «На каких серверах вообще есть истёкший опрос?» и запрашивает подробности только для них. Примерно 4200 запросов в минуту превратились примерно в четыре.

Три миллиона раз «не настроено»

Та же закономерность в другом месте: несколько модулей (записи поддержки, отсутствия, список команды, статистика бота, рассылка) в своих циклах регулярно читали настройки каждого сервера. На большинстве серверов конкретный модуль вообще не настроен, поэтому ответом было «не найдено». Примерно три миллиона раз в день.

Исправление ничем не примечательно: «не настроено» теперь запоминается на 30 минут. Это безопасно только потому, что каждый из этих модулей отправляет боту обновление в тот момент, когда его сохраняют в веб-панели, так что настройка модуля никогда не означает 30 минут ожидания.

Сбои Discord не наши баги

Наш командный канал ошибок публиковал каждое неудачное действие как «Runtime Error», с уникальной ссылкой и всем прочим. Сюда входили и моменты, когда сам Discord отвечал серверной ошибкой. Это не баг на нашей стороне и не то, что мы можем исправить, но в канале это выглядело точно так же, как настоящий дефект.

Сегодня это записывается как предупреждение, а участнику предлагают попробовать ещё раз через несколько секунд, вместо того чтобы давать ссылку для отчёта об ошибке. Канал ошибок, где половина сообщений вовсе не ошибки, в какой-то момент перестают читать. И тогда пропускаешь настоящую.

Атака, которая длилась одну минуту

Однажды днём в конце сентября наша главная страница получила чуть больше 500 000 запросов за одну минуту, сразу из многих стран. Большая часть была остановлена ещё до того, как дошла до наших серверов, и через минуту трафик снова был в норме.

Мы увидели это не потому, что что-то упало. Мы увидели это потому, что число не вписывалось в остальной график. В этом и состоит настоящая задача мониторинга: не бить тревогу, когда всё горит, а показывать, где что-то не вписывается в норму.

Чего наш мониторинг намеренно не видит

Правила здесь так же важны, как и дашборды:

  • Никаких IP-адресов посетителей в логах. Это обещает наша политика конфиденциальности, поэтому мы удаляем их в двух местах: при записи журнала доступа и ещё раз перед сохранением.
  • Никаких ID серверов, пользователей или сообщений в метриках. Каждая метрика разбивается только по грубым признакам (модуль, класс статуса, шард). Это защищает данные и делает базу метрик небольшой.
  • Записи сессий показывают наш интерфейс, а не твой контент. Читаемым остаётся только текст, который слово в слово взят из наших файлов переводов. Названия серверов, каналов и пользователей, вводимые данные и предпросмотры скрыты. Если список разрешённых текстов не удаётся загрузить, скрыто всё.
  • На сайте всё только после согласия. Поэтому и цифры там лишь нижняя граница. Для реального числа просмотров мы смотрим на анонимные итоговые данные нашего сетевого провайдера.

Подробности в политике конфиденциальности.

Что мы из этого выносим

Дорогое редко бывает сломанным. Ни одна из находок выше не вызвала ошибки. Они вызывали нагрузку, расходы и шум, и без измерений ничего из этого не увидишь.

Спрашивать про каждый сервер отдельно не масштабируется. Обе крупные находки были одной и той же закономерностью: цикл по всем серверам, который спрашивает про каждый по отдельности. Ответ почти всегда один и тот же: задать вопрос один раз для всех сразу.

Тревога должна быть редкой, иначе это не тревога. Поэтому команду пингует только Grafana, и только по поводу того, что требует чьего-то вмешательства. Новые типы ошибок из PostHog попадают в канал без пинга.

Если ты сам управляешь сервером Discord и хочешь посмотреть на упомянутые здесь модули: опросы, записи поддержки и отсутствия есть в веб-панели, а описаны они в документации.

Другие статьи