Практическая реализация распределенного...

Post on 17-Dec-2014

1.187 Views

Category:

Documents

4 Downloads

Preview:

Click to see full reader

DESCRIPTION

 

TRANSCRIPT

Comet-серверсвоими руками

Макс ЛапшинДмитрий Демещук

Эволюция веба

Никакого real-time

Немного real-time

Сплошной real-time

После загрузки,

современная страница продолжает

жить своей жизнью.

Возможные варианты• Периодические запросы на сервер• Comet:• Long polling• Websockets• Server Sent Events

• Много запросов впустую

• Постоянная загрузка

• Задержки

Периодические запросы

• Не требует немедленного ответа• Совместим с keepalive• Моментальное обновление

• Много одновременных подключений• Требуется переподключение

Long-polling

• Постоянное соединение• Намного быстрее, чем HTTP• Не везде поддерживаются• Еще не устоялись как стандарт

Выбор очевиден:*

* часто в сочетании с таймером

• Ruby EventMachine• Python Twisted• Node.JS• Erlang

“Стойте, я же могу простосделать это на чистом PHP!”

• CGI - ~1000-2000• Apache - 1000-5000• Node.JS - 1000000 (?)• Erlang - 2277845

Лимит одновременных

подключений

Хранениевнутреннего состояния

• MySQL — надежно и очень медленно• Redis/memcached — ненадежно и медленно• Внутри VM — быстро и опасно• Репликация

Внутреннее состояние хочетсяреплицировать

Почти всегда нужнадоставка сообщений

А еще, очень хочется failover

Нет решений для распределенного комета

из коробки

• Redis - master-slave репликация• RabbitMQ - нет истории• Memcached - нет сообщений

Все приходится делать самим

Нельзя просто так взять

и написать распределенныйcomet-сервер

Нельзя просто так взять

и написать распределенныйcomet-сервер

Почему Erlang• Феноменальная для веба производительность• Феноменальная для веба многоядерность• Распределенность из коробки• Отказоустойчивость• Изоляция данных

DPS - distributed pub/sub

https://github.com/doubleyou/dps

Основные проблемы

Разные профили нагрузки: есть большие каналы и много маленьких.

Лаг между HTTP-ответом и коннектом к

комету: нужна история.

Нет времени на сохранение в SQL БД.

Хроника событий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 добавляется за час

Прикрутили чатик на JS.

Попутно оказалось, чтокроссдоменный long-pollне работает в Safari.

Все круто,

все работает.

Спасибо за внимание

И тут пришли они

Попытка №0:подозрительно

хорошие результаты

Мы просто слали сообщенияи измеряли rps.

(Redis проигралуже на этом этапе)

Вывод:бенчмарки должны

соответствоватьпродакшну

Попытка №1

• Amazon EC2 large instances• 1000 клиентских подключений• 1 rps с каждого клиента

На этот раз,бенчмарк-процессы

работают приближеннок живым клиентам

• 20-140% CPU на одной машине• Репликация все убила

Структура на одной ноде

Репликация между нодами

Асинхронный publishна соседние нодыоблегчил ситуацию,

но не решил проблему.

Все дело в очередях

Низкое время ответаможет быть вредно

Выходы*

• Таймаут на клиенте• Таймаут на сервере• Пользовательские сессии

* лучше - в комбинации

Сессии - почти те же каналы

• В памяти хранить минимум истории• Полную историю хранить на диске, если нужно• Гарантированное время ответа

Производительность

Long polling рассчитанна редкие ответы с сервера.

Как правило, лучше отправитьодин большой HTTP-ответ,чем много маленьких.

Попытка №2:

сервер тянет2000 rps,

хоть и с трудом.

Перевели каналыцеликом на ETS.

Попытка №3:

4000 rps!

Итого

Сервер написани протестирован

за несколько человеко-дней

Неплохая производительность:

WhatsApp - ~11500 rpsDPS - ~4000 rps

Функциональность и железо разные,но порядок цифр похожий.

Важные моменты• Не следует хранить всю историю в памяти• Следите, какие процессы перегружаются• Избегайте избыточных сообщений• Не делайте запросы слишком часто• Используйте пользовательские сессии• Старайтесь не гонять лишние данные

Erlang - не серебряная пуля,но позволяет фокусироваться

на болеевысокоуровневых задачах

Технические компромиссымогут заметно ускорить

работу сервера.

Тесты и бенчмаркис лихвой окупили себя.

Вопросы?

Макс Лапшинmax@maxidoors.ru

Дмитрий Демещукdemeshchuk@gmail.com

top related