Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Comet-сервер своими руками
Search
Dmitry Demeshchuk
October 24, 2012
Programming
1.2k
7
Share
Comet-сервер своими руками
Мой и Макса Лапшина доклад на Highload++ 2012.
Dmitry Demeshchuk
October 24, 2012
More Decks by Dmitry Demeshchuk
See All by Dmitry Demeshchuk
Untitled.pdf
doubleyou
0
120
Other Decks in Programming
See All in Programming
Skillは並べた。動かなかった。契約で繋いだ。— 65個のSkillから、自走する開発サイクルへ
junholee
0
670
Swiftのレキシカルスコープ管理
kntkymt
0
150
TypeScriptだけでAIエージェントを作る フロント・エージェント・インフラのフルスタック実践
har1101
5
770
cloudnative conference 2026 flyle
azihsoyn
1
200
柔軟なPDFレイアウトエディタを支える型システム設計 — Discriminated UnionとConditional Typeの実践
minako__ph
2
230
Augmenting AI with the Power of Jakarta EE
ivargrimstad
0
600
サークル参加から学ぶ、小さな事業の回し方
yuzneri
0
210
権限チェックの一貫性を型で守る TypeScript による多層防御
mnch
3
290
いつか誰かが、と思っていた フロントエンド刷新5年間の実践知
kiichisugihara
1
290
プラグインで拡張される Context をtype-safe にする難しさと設計判断
kazupon
2
230
Cloudflare で始める Data Platform
ta93abe
0
200
AIエージェントの隔離技術の徹底比較
kawayu
0
330
Featured
See All Featured
Mobile First: as difficult as doing things right
swwweet
225
10k
Why Our Code Smells
bkeepers
PRO
340
58k
XXLCSS - How to scale CSS and keep your sanity
sugarenia
250
1.3M
What Being in a Rock Band Can Teach Us About Real World SEO
427marketing
0
230
Digital Projects Gone Horribly Wrong (And the UX Pros Who Still Save the Day) - Dean Schuster
uxyall
0
1.4k
Docker and Python
trallard
47
3.8k
Git: the NoSQL Database
bkeepers
PRO
432
67k
Context Engineering - Making Every Token Count
addyosmani
9
890
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
360
30k
My Coaching Mixtape
mlcsv
0
130
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
47
8.1k
Learning to Love Humans: Emotional Interface Design
aarron
275
41k
Transcript
Comet-сервер своими руками Макс Лапшин Дмитрий Демещук
Эволюция веба
Никакого real-time
Немного real-time
Сплошной real-time
После загрузки, современная страница продолжает жить своей жизнью.
Данные поступают по инициативе сервера
Возможные реализации • Периодические запросы на сервер • Comet: •
Long polling • Websockets • Server Sent Events • Прочее гуано (Flash sockets)
• Много запросов впустую • Постоянная загрузка • Задержки Периодические
запросы
• Не требует немедленного ответа • Совместим с keepalive •
Моментальное обновление • Много одновременных подключений • Требуется переподключение Long-polling
• Постоянное соединение • Намного быстрее, чем HTTP • Не
везде поддерживаются • Еще не устоялись как стандарт
Выбор очевиден:* * часто в сочетании с таймером
• Ruby EventMachine • Python Twisted • Node.JS • Erlang
“Стойте, я же могу просто сделать это на чистом PHP!”
None
• CGI - ~1000-2000 • Apache - 1000-5000 • Node.JS
- 1000000 (?) • Erlang - 2277845 Лимит одновременных подключений
None
Хранение внутреннего состояния • MySQL — надежно и очень медленно
• Redis/memcached — ненадежно и медленно • Внутри VM — быстро и опасно • Репликация
Внутреннее состояние хочется реплицировать
Почти всегда нужна доставка сообщений
А еще, очень хочется failover
Нет решений для распределенного комета из коробки • Redis -
master-slave репликация • Memcached - нет сообщений • Postgres - медленно и без репликации
RabbitMQ • Возможность хранения истории • Возможность использования вебсокетов •
Нет long polling из коробки
Все приходится делать самим
Нельзя просто так взять и написать распределенный comet-сервер Нельзя просто
так взять и написать распределенный comet-сервер
Почему Erlang • Феноменальная для веба производительность • Феноменальная для
веба многоядерность • Распределенность из коробки • Асинхронный IO в последовательном виде • Изоляция данных • Горячее обновление кода
DPS - distributed pub/sub https://github.com/doubleyou/dps
Желаемые фичи • In-memory • История сообщений в канале •
Горячий бэкап нод • Zero-conf, no-ops сервер
Хроника событий 1. Реализация pub/sub-механизма 2. Написание тестов 3. Прикручивание
веб-сервера 4. Доработка напильником 5. Бенчмарки 6. ... 7. PROFIT!
• Распределенный • Автоматический failover • Написан за 2.5 часа
• Меньше 300 строк кода • Один race condition • Один баг-опечатка Первый рабочий pub/sub
dps:subscribe("Channel"). dps:publish("Channel", “Message”).
Тесты • Выявили race condition • Очень помогли в дальнейшей
разработке • Отняли несколько часов • Покрыли примерно 80% кода pub/sub-части • По размеру сравнимы с кодом
Comet добавляется за час http://levgem.livejournal.com/409755.html
Прикрутили чатик на JS. Попутно оказалось, что кроссдоменный long-poll не
работает в Safari.
Все круто, все работает.
Спасибо за внимание!
И тут пришли они Бенчмарки
Попытка №0: подозрительно хорошие результаты
Мы просто слали сообщения 300 000 publishes per second
Вывод: бенчмарки должны соответствовать продакшну
Разные профили нагрузки • Whatsapp: 2M online, 12k pps •
Ejabberd: 40k online, 40k pps
Попытка №1 • Amazon EC2 large instances • 1000 клиентских
подключений • 1 rps с каждого клиента
На этот раз, бенчмарк-процессы работают приближенно к живым клиентам
• 20-140% CPU на одной машине • 2000 deliveries per
second Мы посовещались и решили, что Amazon не очень
Структура на одной ноде
Репликация между нодами
• Асинхронная репликация • Messages discarding • Replication dropping Sacrificial
degradation
Асинхронный publish на соседние ноды облегчил ситуацию, но не решил
проблему.
10 000 deliveries per second с асинхронной репликацией, работает
20 000 deliveries per second - через некоторое время обсыпается
с timeout
Интроспекция в Erlang как она есть
Все дело в очередях
Низкое время ответа может быть вредно
Long polling рассчитан на редкие ответы с сервера. У нас
же он превратился в short-polling.
Выходы* • Таймаут на клиенте • Таймаут на сервере •
Пользовательские сессии * лучше - в комбинации
Сессии - почти те же каналы
7500 publishes per second 150 000 deliveries per second
200 000 deliveries per second обсыпается с timeout
• Клиент шлет сообщение в полную очередь • Отваливается с
таймаутом • Перепосылает в ещё более полную очередь • OOM Killer In Da House Замкнутый круг
Вывод: надо тщательно продумывать rate limit control
• Перед публикацией проверяем длину очередей • Если большая, шлем
HTTP 429 • Клиент сам перепошлет завтра позже Power of Erlang
Итого
Сервер написан и протестирован за несколько человеко-дней
Неплохая производительность: WhatsApp - ~11500 pps DPS - ~7500 pps
Функциональность и железо разные, но порядок цифр похожий.
Важные моменты • Не следует хранить всю историю в памяти
• Следите, какие процессы перегружаются • Избегайте избыточных сообщений • Не делайте запросы слишком часто • Используйте пользовательские сессии • Старайтесь не гонять лишние данные
Erlang - не серебряная пуля, но позволяет фокусироваться на более
высокоуровневых задачах
Тесты и бенчмарки с лихвой окупили себя.
Что дальше? • DHT Ring для распределения каналов • Персистентность
• Регулировка consistency/availability
Технические компромиссы могут заметно ускорить работу сервера. • Не хранить
очереди • Терять сообщения • Отказаться от сессий (в некоторых случаях) • Посылать все в /dev/null
Вопросы? Макс Лапшин
[email protected]
Дмитрий Демещук
[email protected]