Чему нас научил бот на 2000+ серверах Discord
Четыре вещи, которые на большом масштабе работают иначе, чем кажется, пока пишешь код.

Discord-бот на трёх серверах и тот же бот на более чем двух тысячах это не одна и та же программа покрупнее. Горстка допущений, совершенно безобидных в малом, после определённого размера становится именно теми багами, которые найти труднее всего.
Вот четыре, которые стоили нам настоящих сбоев.
1. Сбои распределяются не равномерно, они прячутся
AlphaCloud работает разделённым на несколько процессов, так называемых шардов. Discord решает, какой сервер попадает на какой шард, и каждый шард знает только свои серверы.
Отсюда возникает класс сбоев, которые снаружи выглядят как случайность: приветственные сообщения работают на одних серверах и не работают на других. Ни ошибки в логе, ни алерта, ничего. Причиной был один сетевой вызов без тайм-аута. Если другая сторона принимает соединение и потом замолкает, код ждёт до конца жизни процесса. Всё, что после него, не происходит никогда, а поскольку никакая ошибка не выбрасывается, никто ни о какой ошибке не сообщает.
Урок незрелищный и универсальный: каждому исходящему вызову нужна верхняя граница. Вызов, который ждёт вечно, хуже того, который падает, потому что падение хотя бы видно.
2. Перезапуск это не исправление, а крайний срок
Пока мы не знали причину, перезапуск затронутого шарда надёжно помогал. В этом и проблема перезапусков: они работают и тем самым снимают давление искать причину.
Теперь мы относимся к вопросу "помогает ли перезапуск?" как к диагнозу, а не к лекарству. Если помогает, сломанное состояние живёт в памяти, и в коде есть место, которое его накапливает и никогда не сбрасывает.
Верно и обратное: всё, что должно пережить перезапуск, место в базе данных. Если идёт многошаговая операция, скажем, смена роли у тысяч участников, а процесс посреди неё умирает, операция не должна просто исчезнуть. Её нужно распознать и продолжить при следующем запуске.
3. Лимиты Discord действуют на бота, а не на процесс
Discord ограничивает, сколько запросов в секунду может делать бот. Очевидное допущение: больше процессов, больше пропускной способности. Неверно. Лимит на бота, а не на процесс. Три шарда, у каждого из которых полный бюджет, вместе превышают квоту втрое, и Discord тормозит все три.
Поэтому каждый наш процесс вычисляет, сколько их всего, и берёт только свою долю. Звучит очевидно, но таким не было, и баг долго оставался невидимым, потому что каждый процесс по отдельности выглядел абсолютно корректно.
Родственная ловушка: регулярные задачи работают с фиксированными интервалами, скажем, каждые пять минут. Если все шарды стартуют одновременно, они навсегда запускают свои задачи в одну и ту же секунду. С тех пор каждый процесс при старте получает случайное смещение.
4. То, что люди реально настраивают, не то, чего ты ждёшь
Техническая часть это одна половина. Другая: для большинства серверов значение по умолчанию и есть настройка. Модуль с неправильными значениями по умолчанию неверно настроен на подавляющем большинстве серверов, как бы хороша ни была страница настроек.
Отсюда для нас два вывода. Во-первых, каждое значение по умолчанию требует больше размышлений, чем сама настройка. Во-вторых, лучший вопрос для нового модуля не "что здесь можно настроить", а "что делает этот модуль, если никто ничего не настраивает, и правильно ли это для обычного сервера".
На этом же основано решение, которое поначалу звучит как противоположное: начиная с v1.8.0 почти каждое сообщение бота можно оформить как угодно. Но обязательные блоки, например причину в личном сообщении о предупреждении или меню категорий в панели тикетов, можно перемещать, но нельзя удалить. Свобода оформления да, но не до такой степени, что сервер случайно соберёт то, что выглядит рабочим, а не работает.
Общая нить
Три из четырёх это одна и та же мысль в разных костюмах: на таком масштабе тихий сбой дороже громкого. О падении сообщают, и его чинят. Функция, которая просто перестала что-либо делать, может оставаться такой месяцами, и узнаёшь об этом из баг-репорта от того, кто взял на себя труд написать.
Поэтому первый вопрос, который мы теперь задаём о новом коде, не "работает ли это", а "как это выглядит, когда не работает, и заметим ли мы".
Другие статьи
Как уследить за 4000 серверов Discord: Grafana, PostHog и что они нам показали
Цикл, который незаметно создавал половину нашего трафика, три миллиона бессмысленных запросов в день и атака, закончившаяся через минуту. Что видит наш мониторинг и чего он намеренно не видит.
За кулисамиКогда наш ИИ-провайдер отключил модель
Смена модели, пустые ответы без ошибок и счёт, который внезапно вырос в несколько раз. Что сломалось и почему причину было так трудно увидеть.
За кулисамиПочему почти всё в AlphaCloud остаётся бесплатным
Большинство ботов Discord прячут свои самые полезные функции за подпиской. Мы намеренно так не делаем, и щедрости в этом меньше, чем кажется.