У меня есть приложение python (построено на шаблоне MVC), обслуживаемое сервером Gunicorn с использованием асинхронного рабочего класса (т. Е. Gevent). Это означает, что запросы нескольких клиентов одновременно обслуживаются рабочим процессом. Каждый HTTP-запрос содержит некоторые данные, специфичные для этого запроса, такие как user_id. Произнесите ошибку в модели, и я хочу зарегистрировать ошибку с user_id. Я не хочу продолжать передавать user_id (и некоторые дополнительные запросы) для каждого класса или метода. Я хочу, чтобы эти значения были доступны глобально для любого кода, выполняемого для этого конкретного запроса. Контроллер при получении запроса устанавливает эти значения, а затем любой код, выполняемый для этого запроса, имеет доступ к этим значениям. Выполнение кода для нескольких одновременных запросов должно иметь доступ к их соответствующим значениям данных. Является ли это возможным?Gunicorn с gevent: поддержание на запрос глобальных данных
ответ
Общая идея состоит в том, чтобы связать данные вашего запроса с чем-то, что может быть уникальным для каждого запроса. Например, в качестве значения указывается идентификатор с этим уникальным идентификатором в качестве ключей и данными для каждого запроса.
Поскольку вы говорите, что используете служащих gevent, мы можем использовать greenlet.getcurrent()
как уникальный идентификатор.
Это довольно, что делает Flask + Werkzeug, но они делают это в гораздо более эффективном, эффективном с точки зрения памяти, совместимом с потоками и удобным для пользователя способом, чем мой пример ниже.
Здесь представлено простое приложение wsgi. Здесь a
устанавливается и отправляется по запросу, полученному через функцию «глобально доступная» get_per_greenlet_dict
. В то время как b
передается как параметр, который служит для проверки, что a
верен.
# wsgi.py
import collections, logging, time, greenlet
logging.basicConfig()
log = logging.getLogger(__name__)
log.level = logging.DEBUG
# used to store per-request data
# keys are greenlets, values are dicts
storage = collections.defaultdict(dict)
# return a dict for this request
# TODO: remove the per-request dict at the end of the request
def get_per_greenlet_dict():
return storage[greenlet.getcurrent()]
def application(env, start_response):
# extract query vars
query_vars = env['QUERY_STRING'].split("&")
a = query_vars[0].split("=")[1]
b = query_vars[1].split("=")[1]
# store 'a' in our per-request dict
get_per_greenlet_dict()['a'] = a
log_a_and_b("Before sleep", b)
time.sleep(1)
log_a_and_b("After sleep", b)
start_response('200 OK', [('Content-Type', 'text/html')])
return [b"OK: "]
def log_a_and_b(prefix, b):
# log both a and b,
# where a is sourced from our per-request dict
# and b is passed as a parameter as a means of verifying a
a = get_per_greenlet_dict()['a']
log.debug(prefix + "; a:%s b:%s", a, b)
Запустите gunicorn сервер с GEvent работников:
$ gunicorn -k gevent wsgi
Запуск нескольких simutaneous запросов, скажем по:
$ for i in `seq 1 5`; do curl "127.0.0.1:8000?a=$i&b=$i" & done
Тогда вы увидите выход из gunicorn как:
DEBUG:wsgi:Before sleep; a:2 b:2
DEBUG:wsgi:Before sleep; a:5 b:5
DEBUG:wsgi:Before sleep; a:4 b:4
DEBUG:wsgi:Before sleep; a:1 b:1
DEBUG:wsgi:Before sleep; a:3 b:3
DEBUG:wsgi:After sleep; a:2 b:2
DEBUG:wsgi:After sleep; a:5 b:5
DEBUG:wsgi:After sleep; a:4 b:4
DEBUG:wsgi:After sleep; a:1 b:1
DEBUG:wsgi:After sleep; a:3 b:3
Спасибо. Я пытаюсь werkzeug (http://werkzeug.pocoo.org/docs/0.10/local/), как показано здесь: http://stackoverflow.com/questions/14934885/threads-and-local-proxy-in-werkzeug- использование # 14935819 ответ- – Varun
- 1. Поддержание глобальных результатов игры
- 2. Загрузка глобальных данных для сервера с использованием Flask и gunicorn
- 3. Сделайте запрос на блокировку с запросами при запуске Flask с Gunicorn и Gevent
- 4. Проблемы с supervisord и monit с gunicorn + gevent + pypy
- 5. настройка GEvent-сокет с использованием опоки, Nginx и gunicorn
- 6. утечка памяти с ответами потока gunicorn GEvent и ZeroMQ
- 7. Уменьшение глобальных переменных и поддержание потока функций
- 8. Простой запрос колбы/gevent не работает одновременно
- 9. Запрос на инициализацию глобальных переменных
- 10. gunicorn и websockets
- 11. Gunicorn Workers and Threads
- 12. Когда мне нужно использовать monkey_patch с gevent
- 13. Плохой запрос 400: nginx/gunicorn
- 14. WebSockets и WSGI вместе с Gunicorn
- 15. Настройка gunicorn для Django на Heroku
- 16. Поддержание согласованности данных mongodb
- 17. Поддержание сценариев базы данных
- 18. Есть ли способ запустить GEvent-socketio 0.3.5-RC2 с gunicorn 18,0 без снижения
- 19. PyOpenCl литье глобальных данных
- 20. Приложение Falcon с использованием Gunicorn на киосках Heroku
- 21. Настройка Gunicorn с зашифровать ДАВАЙТЕ CERT
- 22. Использование PyQt с gevent
- 23. gunicorn нити на Heroku
- 24. Проблема с параллельным соединением колбочек, обслуживаемая GUnicorn
- 25. GEvent ломает запросы/urllib2 таймаута
- 26. Procfile gunicorn custom module name
- 27. Поддержание целостности данных порядка с постоянными редактирует
- 28. Как запрос Gunicorn направить в колбу
- 29. Явный переключатель() с gevent
- 30. Поддержание конфиденциальности конфиденциальных данных клиентов
Конечно, взгляните на колбу и как она ndles эти глобальные. Вы можете в основном импортировать модули как обычно в Python и иметь доступ к текущему объекту запроса и другим материалам, которые вы, возможно, захотите поместить в глобальную область. Вот интересующий вопрос с интересным пониманием: http://stackoverflow.com/questions/15083967/when-should-flask-g-be-used – Alp