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
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
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
ローカルLLMを使ってB2Bサービスを作っていての学び
yaotti
0
220
AIで効率化できた業務・日常
ochtum
0
150
Observability in Practice:Grafana 與 Edge Device SRE 的那些事
blueswen
0
180
メソッドのジェネリクスでGoの夢は広がるか? / Kyoto.go #65
utgwkk
3
990
IBM Bobを活用したレガシーアプリの最新化
oniak3ibm
PRO
1
220
Spring Security 実践 ─ GraphQL APIで実務に役立つ 認証・認可 を学ぶ
wagyu
0
260
Semantic Version 単位で戦略を柔軟に変えて、パッケージアップデートを自動化する
daitasu
1
320
ローカルLLMでどこまでコードが書けるか -拡張版 / How much code can be written on a local LLM Extended
kishida
12
4.5k
Javaの型とAI時代に型が大事な理由 / java types and type in AI era
kishida
2
150
JavaDoc 再入門
nagise
1
430
LaravelLive Japan の裏方のすべて — 第188回 PHP勉強会@東京 (2026-06-24)
suguruooki
2
130
Agentic UI
manfredsteyer
PRO
0
200
Featured
See All Featured
No one is an island. Learnings from fostering a developers community.
thoeni
21
3.8k
New Earth Scene 8
popppiees
3
2.4k
Large-scale JavaScript Application Architecture
addyosmani
515
110k
Bash Introduction
62gerente
615
220k
世界の人気アプリ100個を分析して見えたペイウォール設計の心得
akihiro_kokubo
PRO
72
40k
Technical Leadership for Architectural Decision Making
baasie
3
430
Agile Actions for Facilitating Distributed Teams - ADO2019
mkilby
0
210
Design and Strategy: How to Deal with People Who Don’t "Get" Design
morganepeng
133
19k
Performance Is Good for Brains [We Love Speed 2024]
tammyeverts
12
1.7k
Between Models and Reality
mayunak
4
360
Site-Speed That Sticks
csswizardry
13
1.2k
Save Time (by Creating Custom Rails Generators)
garrettdimon
PRO
32
3.6k
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]