ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

python – 带gevent的Gunicorn:维护每个请求的全局数据

2019-06-28 11:45:23  阅读:233  来源: 互联网

标签:python asynchronous gunicorn gevent


我有一个使用异步工作类(即gevent)的Gunicorn服务器提供的python应用程序(基于MVC模式构建).这意味着工作进程同时提供多个客户端请求.
每个http请求都包含一些特定于该请求的数据,如’user_id’.说模型中发生错误,我想记录
user_id出错.我不想继续将user_id(以及一些更具请求的特定值)传递给每个类或方法.我希望这些值对于为此特定请求执行的任何代码都是全局可用的.接收请求的控制器设置这些值,然后为此请求执行的任何代码都可以访问这些值.为多个同时请求执行的代码应该可以访问它们各自的数据值.可能吗?

解决方法:

一般的想法是将每个请求数据与每个请求唯一的内容相关联.例如,有一个dict,这个唯一标识符作为键,每个请求数据作为值.

既然你说你正在使用gevent worker,我们可以使用greenlet.getcurrent()作为唯一标识符.

这几乎就是Flask Werkzeug所做的事情,但他们以比我下面的例子更高效,内存效率,线程兼容和最终用户友好的方式这样做.

这是一个简单的wsgi应用程序作为示例.这里是通过’全局可用’函数get_per_greenlet_dict在每个请求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)

使用gevent worker运行gunicorn服务器:

$gunicorn -k gevent wsgi

运行多个同时请求,例如:

$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

标签:python,asynchronous,gunicorn,gevent
来源: https://codeday.me/bug/20190628/1315136.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有