27 января 2014 г.

Реальный мир. Вебсокеты на production-сервере

Технология WebSocket потихоньку входит в повседневную рутину веб-разработчиков. В сети есть куча материала, и писать еще что-то о том, как реализовать ее в своём приложении (как на уровне бэкенда, так и на уровне фронтенда) не имеет никакого смысла.

Эта история о другом.

В своем самом свежем проекте Psychedelizer, веб-сервисе для демонстрации (и не только) моей библиотеки для психоделической обработки изображений, я использую на серверной стороне фреймворк Tornado для предоставления RESTful API клиенту, асинхронных операций с MongoDB и обработки вебсокетов. Реализация подобного функционала с использованием данного фреймворка — довольно тривиальная задача. Так, к примеру, у меня выглядит простой обработчик вебсокетов, рассылающий разные обновления по клиентам:
Само собой, всё это идеально работает в девелоперской среде. Но вот с работоспособностью на production-сервере у меня возникли проблемы.

В самом начале вебсокеты вообще не работали. После некоторого гугления выяснилось, что версия Nginx из репозитория Debian Stable еще не поддерживает их. Тогда была установлена более свежая версия из официального репозитория проекта и переписан конфиг.

Но вебсокеты все ещё отказывались работать как полагается. Обновления не рассылались по клиентам, хотя соединение клиент-сервер устанавливалось исправно. Ситуация казалась мне какой-то идиотической, пока я не понял, в чем дело.

Сначала я думал, что приложение по какой-то причине не сохраняет клиента в список. Но во время отладки этот вариант быстро отпал. Потом пришло озарение. На самом деле я просто был слеп.
На сервере под балансировщиком Nginx'а крутится 8 инстансов моего приложения (на каждое ядро). При загрузке страницы запрос на соединение с вебсокетом направляется, конечно, только на один из них. И, само собой, запись о новом клиенте сохраняется только в каком-то из восьми инстансов. Такие вот дела.

В качестве временной меры я написал простой ajax-апдейтер. Потом посмотрю, что с этим можно сделать. Думаю, можно реализовать отдельностоящий websocket-сервер, который будет дергаться из Tornado-приложения при обновлении контента. На этом всё. Исходники сервиса и библиотеки доступны на GitHub: aluminiumgeek/psychedelizer

Комментариев нет:

Отправить комментарий