Интернет

Свой CDN, свои нейросети и ни строчки jQuery: как устроен ДуровЛох изнутри

ДуровЛох работает с 2010 года. За это время в его базе накопилось 206 224 аккаунта, 2,52 миллиона фотографий, около 510 тысяч личных сообщений, 6 403 сообщества и примерно 26,6 тысячи аудиозаписей. Первый аккаунт в базе зарегистрирован ещё в 2010-м. Всё это держит один человек, Константин Соколов. Если не считать стажёра, над проектом он работает один.

В интервью Durov Inside Соколов ответил про начинку в трёх словах: «Старый добрый PHP». Мы решили выяснить, что за ними стоит. Оказалось, PHP здесь только верхушка.

Основа: скучный стек без сюрпризов

Сайт работает на связке nginx и PHP-FPM. Код держится в OPcache, так что PHP не разбирает файлы заново на каждый запрос. Данные лежат в MariaDB, всё горячее хранится в memcached. Никаких модных фреймворков. Скучный стек здесь звучит как комплимент: в нём нечему внезапно сломаться.

Сама база весит около 2,2 ГБ. Для соцсети с шестнадцатилетней историей это очень компактно.

Как ДуровЛох держит нагрузку

Главный принцип: не делать одну и ту же работу дважды. Самое востребованное отдаётся мимо базы. Карточки профилей, сообществ, видео и обсуждений живут в memcached. Работа с кешем завёрнута в собственный класс: у ключей свой префикс, а время жизни задаётся для каждого ключа отдельно.

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

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

Статика уходит сжатой: brotli для современных браузеров, gzip для остальных. Файлы с версией в адресе (?v=) браузер хранит год и считает неизменными, поэтому даже не спрашивает сервер, не обновились ли они. Новая версия просто получает новый адрес. Всё остальное кешируется на срок от недели до 30 дней.

Фронтенд без jQuery и без сборщика

Снаружи ДуровЛох выглядит как тот самый ВКонтакте, который многие помнят. Внутри это одностраничное приложение. Переходы между разделами идут через history.pushState: страница не перезагружается, подтягивается только нужное. Для старых браузеров есть запасной путь.

У каждого адреса на сайте есть свой обработчик и свой набор CSS и JS. Этой картой маршрутов управляет собственный загрузчик stManager. Он дожидается нужных стилей и скриптов и только после этого показывает страницу. Если файл не загрузился, загрузчик пробует ещё раз. На плохом интернете человек не увидит развалившейся вёрстки.

jQuery из проекта вычищен полностью, его место заняли собственные небольшие помощники. Весь JavaScript написан на ES5 и идёт в браузер без транспилятора: что написал Соколов, то браузер и выполняет. Отсюда и обещание из интервью: сайт открывается даже на очень старом ноутбуке.

Свой CDN

Фото и видео отдаёт не основной сайт, а отдельный медиасервер на поддоменах вида cnN. Для каждого файла в базе записан номер хоста. Хранилище можно разложить на несколько серверов, и сайт всегда знает, где лежит конкретная картинка.

Внутри файлы разбросаны по тысяче случайных томов, так что ни в одной папке не копятся миллионы файлов. В имени каждого файла зашит случайный секрет: адрес нельзя угадать или подобрать. Сейчас в хранилище около 200 ГБ фотографий и около 590 ГБ видео, всего примерно 800 ГБ.

Загрузка устроена строго. Принимаются только разрешённые типы файлов. Картинку сервер не просто сохраняет, а пересобирает заново через GD. Из неё исчезают EXIF-данные, включая координаты съёмки, и заодно обезвреживаются файлы-полиглоты, в которых под видом картинки прячется что-то ещё. Сразу нарезаются четыре размера: 770, 604, 216 и 100 пикселей. Каждый экран получает ровно ту картинку, которая ему нужна.

С видео отдельный конвейер. Сначала ffprobe проверяет, что внутри действительно видеоконтейнер. Потом ролик встаёт в очередь, которую разбирает фоновая задача. ffmpeg перекодирует его в H.264 со звуком AAC и с faststart, поэтому видео начинает играть сразу, без ожидания полной загрузки. Превью берётся из середины ролика, а не с чёрного первого кадра.

«Ваши нюдсы в безопасности»

Эту фразу Соколов бросил в интервью и в подробности вдаваться не стал. Кое-что мы всё-таки узнали.

Фото из личных сообщений хранятся отдельно от публичных, и обычной ссылкой до них не добраться. Открыть такой файл можно только по подписанной ссылке, которая живёт ограниченное время. PHP проверяет подпись, даже не обращаясь к базе, а сам файл отдаёт nginx через X-Accel-Redirect. Скопированная ссылка через какое-то время просто перестаёт открываться.

Как именно устроена подпись, Соколов не рассказывает. И правильно делает.

Модерация: нейросети на своём железе

Многие площадки отдают модерацию внешним сервисам, а вместе с ней и контент пользователей. ДуровЛох так не делает: нейросети работают локально, без внешних API.

Картинки проверяет детектор наготы NudeNet на ONNX Runtime. Тексты разбирает многоязычный классификатор токсичности на основе XLM-RoBERTa, он понимает русский и английский.

Всё новое попадает в очередь: посты, комментарии, сообщения, фото и видео. Фоновый обработчик проходит по ней каждую минуту. Он защищён от двойного запуска и умеет повторять попытки. Если модель недоступна, материал ждёт своей очереди и никуда не теряется.

Текст проверяется в три слоя:

Правила. Ловят приглашения в другие мессенджеры и типичный спам про «заработок» и криптовалюту.

Эвристики. Замечают слишком много ссылок, сплошной капс и один и тот же текст, отправленный повторно за десять минут.

Нейросеть. Подключается для текстов длиннее 20 символов.

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

По умолчанию автоматика работает мягко: помечает материал и записывает его в журнал для модератора, но ничего не скрывает. Последнее слово остаётся за человеком. Исключение одно: откровенная нагота, в которой модель уверена. Такое скрывается сразу, а пограничные случаи только помечаются.

С жалобами похожая логика. Если на один материал за сутки пожаловались три разных человека, он скрывается автоматически. У каждого есть дневной лимит жалоб, так что завалить кого-то жалобами в одиночку не выйдет. Жалобы на личные сообщения автоматика не трогает, их разбирают только вручную.

Капча тоже своя. Никаких сторонних виджетов на странице.

Выкатка без сюрпризов

«Перед каждым обновлением делаем копию и проверяем всё ещё раз», — сказал Соколов в интервью. На деле за этим стоит целый конвейер.

Код уезжает на сервер через rsync с длинным списком исключений. Конфиги, секреты и медиа пользователей в выкладку не попадают никогда. Перед отправкой каждый PHP-файл проверяется через php -l, а список файлов проверяется на секреты. Контрольные суммы md5 сверяются с продом: если какой-то файл на сервере изменился с момента подготовки релиза, выкатка останавливается сама. Ни одна правка не будет молча затёрта.

Крупные релизы идут фазами:

проверка → бэкап → миграции → медиа- и API-сервер → основной сайт → данные → смоук-тесты

Перед настоящим запуском весь сценарий прогоняется вхолостую. Бэкап снимается на обоих серверах, и к каждому релизу прилагается пошаговая инструкция отката.

После выкатки сайт проверяют глазами анонимного посетителя: curl без авторизации смотрит коды ответов, редиректы и карту сайта. Отдельно проверяется, что API без токена отвечает отказом, а приватные медиа остаются закрытыми. Заметки об обновлении бот сам публикует в канале в мессенджере MinChat.

API и приложение

У ДуровЛоха есть API, совместимый с форматом ВКонтакте: методы вызываются по адресам вида /method/… На нём работает приложение для Android, которое, как и сайт, запускается даже на старых телефонах.

Что остаётся за кадром

Свой CDN, своя модерация, свой загрузчик, своя капча и выкатка с защитой от самого себя. Обычно это работа целого отдела. Здесь это работа одного человека, который, по его словам, за вечер может собрать несколько рабочих MVP. Как ему это удаётся, мы разбирали в отдельном материале.

Про многое Соколов по-прежнему молчит. Похоже, старый добрый PHP в его руках не такой уж и старый.

разработка ДуровЛох

Обсуждение

Комментариев пока нет.

Читайте также