Несколько рабочих с gevent-socketio не работают с транспортом xhr-polling из-за сеансов

В настоящее время я пытаюсь масштабировать gevent-socketio между несколькими рабочими серверами с сервером пушки, используя рабочий < strong>socketio.sgunicorn.GeventSocketIOWorker. Я использую веб-сокеты, когда они существуют, в противном случае я заставляю XHR-опрос (для IE и т. д.).

XHR-опросу нужен сеанс, чтобы отслеживать следующие опросы, но как только я перехожу от одного к двум или более воркерам, запросы начинают распространяться между собой, что означает потерю состояния и все ломается.

Я думаю, что следующие строки кода имеют значение: https://github.com/abourget/gevent-socketio/blob/master/socketio/handler.py#L104-106 Полагаю, мне нужен какой-то другой механизм хранения, например redis, который я использую для обычного pubsub -actions, но это глубоко внутри реальной библиотеки.

Итак, мой вопрос заключается в том, как мне перейти от хранилища сеансов в памяти к другому серверному движку глобально в моем приложении (изящно ли он переопределяет код сеанса в приведенной выше ссылке?) без необходимости изменять саму библиотеку ? Что-то вроде директив сеанса PHP в php.ini. Я полагаю, что можно привести аргумент, что это очень общий вопрос о питоне, но у меня возникли проблемы с поиском соответствующей информации, и я также не уверен, что это сработает для этой библиотеки.

Или, в качестве альтернативы, как мне использовать транспорт xhr-опроса gevent-socketio между разными рабочими и серверами (без прилипания)?

Спасибо!


person moodh    schedule 22.10.2012    source источник
comment
Просто идея: хранить информацию о сеансе в файлах cookie? Своего рода ОТДЫХ.   -  person ivan_pozdeev    schedule 28.10.2012
comment
@moodh Вы когда-нибудь решали это? Кроме того, действительно ли несколько работников действительно помогают? Сам Gevent отлично справляется с обработкой многих вызовов в одном цикле событий.   -  person pors    schedule 09.01.2014
comment
Нет, я сдался и вместо этого начал использовать pusher.com. В gevent-socketio есть несколько билетов (github.com/abourget/gevent-socketio/issues/ 112) относительно этой проблемы, но я не знаю, как далеко они продвинулись. К сожалению :)   -  person moodh    schedule 09.01.2014


Ответы (3)


Очевидно, это ограничение socketio. Из того, что я вижу в Интернете, обработка сеанса обычно выполняется на уровне веб-фреймворка, а не на уровне веб-сервера. socketio пытается сделать это на своем собственном нижнем уровне и делает это ограниченным образом. Я предполагаю, что авторы думали, что полноценное решение будет излишним. В вашем случае они оказались неверными.

Есть только два способа преодолеть ограничения, требующие изменения логики: исправление исходного кода и исправление во время выполнения. Выбирайте то, что вам больше всего нравится (или, ну, меньше всего противно :^)). Для 2-го варианта я предлагаю заменить request_tokens и/или код, который его создает, на другой объект с таким же интерфейсом. По причинам, изложенным в 1-м абзаце, я действительно думаю, что авторы socketio вероятно, примет исходный патч, который позволит ему использовать внешние механизмы обработки сеансов, если вы его предложите.

Стандартные места для информации о сеансе: общая память, файлы, база данных. Я предлагаю вам изменить логику таким образом, чтобы socketio использовал тот же механизм, что и ваша веб-инфраструктура (или что-то еще, составляющее ваши страницы).

person ivan_pozdeev    schedule 28.10.2012
comment
Спасибо за ответ! Хотя это не решение, я все равно дам награду за вашу информацию. Я подожду фактического решения, но ваш ответ помог мне еще больше понять проблему. Я почти уверен, что мы решим эту проблему, заменив request_tokens, как вы предложили. Спасибо за ответ! - person moodh; 31.10.2012
comment
2moodh: Я предложил исправить использование того же механизма, что и ваш веб-фреймворк. Так что невозможно писать, не зная, что это за механизм. - person ivan_pozdeev; 31.10.2012
comment
Я использую Redis для поддержания сеансов между работниками и серверами, ничего особенного для flask (используемой мной платформы). Возможно, можно позволить Flask использовать Redis, но я еще не изучал это. :) - person moodh; 31.10.2012
comment
Я сделал все возможное, чтобы разработать фактическое решение, но оказалось слишком сложно найти все тонкости, просто перемещаясь по коду, не заглядывая в реальную систему во время выполнения. Кажется, что request_tokens dict состоит из файла cookie (поэтому он должен сохраняться между запросами), и я не мог отследить происхождение других серверных сущностей, которые использует код. Я действительно не думаю, что 20 баллов оправдывают дальнейшие затраты времени. - person ivan_pozdeev; 08.12.2012
comment
ivan_pozdeev: Спасибо за попытку! github.com/abourget/gevent-socketio/issues/112 вот активный билет с текущей проблемой, а также. :) - person moodh; 09.12.2012

Посмотрите примеры здесь:

https://github.com/abourget/gevent-socketio/tree/master/examples/pyramid_backbone_redis_chat_persistence

Он показывает, как использовать Redis в качестве распределенной очереди сообщений.

person sontek    schedule 23.11.2012
comment
Я уже использую Redis внутри самого приложения, и оно отлично работает. Вы, кажется, не понимаете мою проблему, хотя. Проблема заключается в том, что обработка сокетов с длинным опросом находится глубоко в самой библиотеке. :) - person moodh; 23.11.2012

Просто мысль, так как у меня такая же проблема; вместо того, чтобы позволить разветвлению gunicorn (с флагом -w), возможно, вы могли бы создать несколько процессов gunicorn на разных портах, а затем использовать nginx для балансировки на них, используя блок "upstream" с "прикрепленным" сеансом. Я считаю, что именно так реализация nodejs обрабатывает многопроцессорность рабочих процессов, когда они не разделяют состояния с Redis.

person simpoir    schedule 19.03.2015