Делить состояние между потоками в бутылке - PullRequest
0 голосов
/ 20 декабря 2018

В моем приложении Bottle , работающем на pythonanywhere , я хочу, чтобы объекты сохранялись между запросами.

Если я напишу что-то вроде этого:

X = {'count': 0}

@route('/count')
def count():
    X['count'] += 1
    tpl = SimpleTemplate('Hello {{count}}!')
    return tpl.render(count=X['count'])

Количество увеличивается, что означает, что между запросами сохраняется X.

В настоящее время я выполняю это на pythonanywhere , который является управляемой службой, где я не могу контролировать веб-сервер (nginx, я полагаю?) многопоточность, балансировка нагрузки (если есть) и т. д. *

Мой вопрос заключается в том, является ли это совпадением, потому что он использует только один поток при минимальной загрузке от меня, выполняющего мои тесты?

В целом, в какой момент это перестанет работать?Например, у меня есть более одного сервера с потоком / сокетом / экземпляром / балансировкой нагрузки и т. Д.? ... *

Помимо этого, каковы мои лучшие варианты, чтобы сделать что-то подобное (придерживаясь бутылки), даже если у меня естьперейти на сервер barebones.

Вот что Документы по бутылкам должны сказать о своем запросе объекте:

Потоково-безопасномэкземпляр LocalRequest.Если доступ осуществляется из обратного вызова запроса, этот экземпляр всегда ссылается на текущий запрос (даже на многопоточном сервере).

Но я не до конца понимаю, что это значит, или где глобальные переменныекак тот, который я использовал, в отношении многопоточности.

Ответы [ 2 ]

0 голосов
/ 24 января 2019

Я отвечаю на вопросы, связавшись со службой поддержки PythonAnywhere, у которой было следующее:

Когда вы запускаете веб-сайт на бесплатной учетной записи PythonAnywhere, только один процесс обрабатывает всеваши запросы - так что глобальная переменная, подобная той, которую вы используете, будет в порядке.Но как только вы захотите увеличить масштаб и получить (скажем) учетную запись хакера, у вас будет несколько процессов (не потоков), и, конечно, у каждого будут свои глобальные переменные, так что все пойдетнеправильно.

Так что эта часть имеет дело со спецификой PythonAnywhere о том, почему он работает и когда он перестанет работать там.

Ответ на вторую часть о том, как поделитьсяпеременные между несколькими процессами Bottle, я также получил их поддержку (наиболее полезную!), когда они поняли, что база данных не будет работать хорошо в этой ситуации.

Разные процессы, конечно, не могут совместно использовать переменные, и самое жизнеспособное решениебудет:

написать свой собственный сервер кэширования для хранения содержимого в памяти [...] У вас будет один процесс, который выполняется все время, и запросы веб-API получат доступэто как-то (внутренний REST API?).Он может хранить вещи в памяти [...]

Ps: я не ожидал, что другие ответы скажут мне сохранить состояние в базе данных, я решил, что факт, который я спрашиваю, означаетУ меня есть веская причина не использовать базу данных, извиняюсь за потраченное время!

0 голосов
/ 20 декабря 2018

TL; DR: Вы, вероятно, захотите использовать внешнюю базу данных для хранения своего состояния.

Если ваше приложение крошечное и вы планируете всегда запускать ровно один серверный процесс, то ваштекущий подход может работать;«все», что вам нужно сделать, это получить блокировку каждого (!) доступа к общему состоянию (dict X в вашем примере кода).(Я поставил «все» в кавычки там, потому что это, вероятно, станет сложнее, чем кажется на первый взгляд.)

Но, так как вы спрашиваете о многопоточности, я предполагаю, что ваше приложение болееигрушка, означающая, что вы планируете получать значительный трафик и / или хотите обрабатывать несколько запросов одновременно.В этом случае вам понадобится несколько процессов, а это означает, что ваш подход - сохранение состояния в памяти - не может работать.Память не распределяется между процессами.(Общий) способ совместного использования состояния между процессами - это сохранение состояния извне, например, в базе данных.

Вы знакомы с Redis?Это было бы в моем коротком списке кандидатов.

...