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
7
1.2k
Comet-сервер своими руками
Мой и Макса Лапшина доклад на Highload++ 2012.
Dmitry Demeshchuk
October 24, 2012
Tweet
Share
More Decks by Dmitry Demeshchuk
See All by Dmitry Demeshchuk
Untitled.pdf
doubleyou
0
120
Other Decks in Programming
See All in Programming
クラウドに依存しないS3を使った開発術
simesaba80
0
220
ZJIT: The Ruby 4 JIT Compiler / Ruby Release 30th Anniversary Party
k0kubun
1
310
Patterns of Patterns
denyspoltorak
0
420
Denoのセキュリティに関する仕組みの紹介 (toranoana.deno #23)
uki00a
0
220
Cap'n Webについて
yusukebe
0
160
Findy AI+の開発、運用におけるMCP活用事例
starfish719
0
2.1k
例外処理とどう使い分ける?Result型を使ったエラー設計 #burikaigi
kajitack
16
4.7k
Context is King? 〜Verifiability時代とコンテキスト設計 / Beyond "Context is King"
rkaga
10
1.5k
リリース時」テストから「デイリー実行」へ!開発マネージャが取り組んだ、レガシー自動テストのモダン化戦略
goataka
0
160
脳の「省エネモード」をデバッグする ~System 1(直感)と System 2(論理)の切り替え~
panda728
PRO
0
130
16年目のピクシブ百科事典を支える最新の技術基盤 / The Modern Tech Stack Powering Pixiv Encyclopedia in its 16th Year
ahuglajbclajep
2
490
AtCoder Conference 2025「LLM時代のAHC」
imjk
2
650
Featured
See All Featured
Odyssey Design
rkendrick25
PRO
0
450
Dealing with People You Can't Stand - Big Design 2015
cassininazir
367
27k
A Guide to Academic Writing Using Generative AI - A Workshop
ks91
PRO
0
170
Un-Boring Meetings
codingconduct
0
170
Why Mistakes Are the Best Teachers: Turning Failure into a Pathway for Growth
auna
0
34
Leveraging LLMs for student feedback in introductory data science courses - posit::conf(2025)
minecr
0
100
Effective software design: The role of men in debugging patriarchy in IT @ Voxxed Days AMS
baasie
0
190
Building a A Zero-Code AI SEO Workflow
portentint
PRO
0
230
Code Reviewing Like a Champion
maltzj
527
40k
Discover your Explorer Soul
emna__ayadi
2
1k
No one is an island. Learnings from fostering a developers community.
thoeni
21
3.6k
More Than Pixels: Becoming A User Experience Designer
marktimemedia
2
280
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]