Realtime Web
Решил разобраться что и как у нас с realtime в современном Вебе.
Для примера возьмем какую-нибудь онлайн игру, для которой важны (в порядке важности):
1. Streaming данных с сервера в реальном времени (с минимальной задержкой)
2. Время отклика на действия игрока
3. Возможность работы через прокси
Пункт 3й желателен, но не обязателен.
Из средств будем использовать HTML, js, python, при этом не очень хочется использовать twisted. Желательно хотя бы tornado.
Какие есть варианты:
1. Long running AJAX
Что такое: делаем запрос на сервер, который ждет ответа неограниченно долго. После получения ответа делаем запрос еще раз. И так до бесконечности.
Существует в нескольких вариациях: с использованием XHR, с использованием скрытого фрейма и так далее.
Проблемы:
- Бьет по производительности, т.к. мы сами разрешили клиентам долбить наш веб сервер
- Время отклика сильно зависит от нагруженности веб морды
- Синхронные фреймворки использовать нельзя, а юзать асинхронные не сильно удобно. Вариант решения - nginx который будет распределять запросы по маске между 2 бекендами, один на той же Сварге, а второй на торнадо.
- Нельзя напрямую обращаться к серверу на другом порту/тазике из за ограничений AJAX на тему cross domain scripting.
Достоинства:
- Работает везде
- Поддержка проксей
2. Cometd, он же Bayeux Protocol
По сути, попытка “стандартизации” long polling request’ов. Может работать как в обычном long polling режиме, так и с извратом - открывается 2 соединения, где одно соединение используется для отсылки данных к серверу, а другое - для отсылки данных от сервера.
Описывать буду именно режим с двумя соединениями.
Проблемы:
- Для питона поддерживается только Cometd, который написан поверх Twisted
- Twisted :-)
- Протокол относительно сложный, да и синхронизировать 2 соединения в одно логическое не очень удобно
Достоинства:
- Время отклика сильно лучше
3. WebSockets
Попытка добавить сокеты к клиентскому JS. Открываем соединение с помощью HTTP протокола, сервер видит что это именно WebSocket и дальше его как-то обрабатывает.
Проблемы:
- Почти никто из браузеров не поддерживает
- Те кто поддерживают - отключили из за найденной дыры в протоколе
- Финальных спеков нет, 76 ревизий настораживают.
- Всякие там кеширующие прокси не умеют и не понимают (nginx, например). Есть HAProxy, но делать цепочку Client -> HAProxy -> nginx -> wsgi не очень хочется.
Достоинства:
- Сокеты в JS, ура!
Кстати, я так и не понял зачем было городить это все. Со времен появления SSL был такой HTTP метод как CONNECT. Его отлично понимали proxy, его легко можно прикрутить к веб серверу. Если нужно различать куда стучимся - используем custom header, делов то. Даже если будет срабатывать same origin policy для JS, то на всех существующих проксях (nginx например) легко можно будет заворачивать трафик куда надо по хидеру.
4. socketjs & co
Идея тоже весьма простая - делаем мелкий флешовый скрипт, который средствами флеша имитирует работу обычного tcp сокета. Работает везде где есть флеш.
Достоинства:
- Легко использовать
- Чистый tcp
- Быстрый
- Работает почти везде (найти юзера у которого нет флеша нынче тяжело)
Недостатки:
- Завязка на флеш
- Надо писать свой сетевой протокол, т.к. ничего готового нет.
5. js-amqp
Есть такая штука как AMQP (Advanved Messaging Queue Protocol) который позволяет создавать очереди сообщений. К сожалению, протокол overdesigned, т.е. его использовать не очень удобно, но production-ready решения есть, например RabbitMQ, ActiveMQ и т.д.
По сути, браузер коннектится к AMQP серверу и получает/отправляет собщения. Все круто, но использовать AMQP для передачи сообщений между клиентом и сервером это как палить из пушки по воробьям.
Недостатки:
- Сложный и неэффективный протокол (первоначальный автор спецификаций AMQP от него отказался и решил делать ZeroMQ)
- Большая половина функциональности использоваться не будет
- Интеграция js-amqp представляет собой флешовый скрипт с неким JS API.
Достоинства:
- Не заморачиваемся со своим сетевым протоколом
- Быстрее long polling ajax, медленнее сырых сокетов
6. Использовать Mongrel2 как фронтенд
Mongrel2 это такая штука, которая ловит входящие запросы (HTTP, TCP, etc) и конвертирует их в сообщения ZeroMQ. Подписчики на эти сообщения их обрабатывают и отправляют ответ обратно к Mongrel2, который уже отправляет их на клиент.
Достоинства:
- Получаем ZeroMQ из коробки (т.е. заодно и хорошую расширяемость на будущее)
Недостатки:
- Не решает вопроса с транспортом от браузера к серверу
- Слишком новая технология
- Нет никаких тестов
- Никто не писал об опыте использования
Это как бы все что я смог накопать.
Какие еще есть идеи:
- ZeroMQ
Отличная штука - сокеты на стероидах, с гарантированной доставкой в случае потери tcp соединения и так далее. Есть интеграции почти со всеми языками, включая node.js.
Но. Интеграция всегда завязана на Сишную либу, которая уже и занимается протоколом. Т.е. даже интеграция на Java тянет за собой сишную либу.
Нативных клиентов (например как для redis) нет вообще.
Подумываю написать клиент на жаваскрипте поверх socketjs, благо протокол там ну очень простой. Но это когда-нить потом.
Итог
Я вот даже не знаю на чем остановиться. Использовать Cometd не очень хочется, там страшный Twisted. Делать все на AMQP - overkill. Писать свой wire протокол поверх WebSockets/socketjs - не хочется, но чую прийдется.
P.S. Я нашел его! Смотреть тут: https://github.com/SocketTornadIO/SocketTornad.IO