2015-09-11 2 views
3

У меня есть приложение python (построено на шаблоне MVC), обслуживаемое сервером Gunicorn с использованием асинхронного рабочего класса (т. Е. Gevent). Это означает, что запросы нескольких клиентов одновременно обслуживаются рабочим процессом. Каждый HTTP-запрос содержит некоторые данные, специфичные для этого запроса, такие как user_id. Произнесите ошибку в модели, и я хочу зарегистрировать ошибку с user_id. Я не хочу продолжать передавать user_id (и некоторые дополнительные запросы) для каждого класса или метода. Я хочу, чтобы эти значения были доступны глобально для любого кода, выполняемого для этого конкретного запроса. Контроллер при получении запроса устанавливает эти значения, а затем любой код, выполняемый для этого запроса, имеет доступ к этим значениям. Выполнение кода для нескольких одновременных запросов должно иметь доступ к их соответствующим значениям данных. Является ли это возможным?Gunicorn с gevent: поддержание на запрос глобальных данных

+0

Конечно, взгляните на колбу и как она ndles эти глобальные. Вы можете в основном импортировать модули как обычно в Python и иметь доступ к текущему объекту запроса и другим материалам, которые вы, возможно, захотите поместить в глобальную область. Вот интересующий вопрос с интересным пониманием: http://stackoverflow.com/questions/15083967/when-should-flask-g-be-used – Alp

ответ

2

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

Поскольку вы говорите, что используете служащих 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 
+0

Спасибо. Я пытаюсь werkzeug (http://werkzeug.pocoo.org/docs/0.10/local/), как показано здесь: http://stackoverflow.com/questions/14934885/threads-and-local-proxy-in-werkzeug- использование # 14935819 ответ- – Varun

Смежные вопросы