gpt4 book ai didi

django - GEvent/GUnicorn 和 C10k 问题

转载 作者:行者123 更新时间:2023-12-01 02:16:15 29 4
gpt4 key购买 nike

C10K problem告诉我们传统的 Web 服务器最多只能同时限制约 10k 的容量。

像 nginx 这样的服务器使用单线程模型和异步通信而不是线程来处理传入的请求。阿法克Gevent使用 greenlets (同一线程内的可切换执行上下文)而不是线程。

这让我想到了两个问题(再次:假设我们处于异步模型中 - 考虑 gevent 和 gunicorn):

  • 在这种情况下:是否存在资源占用的风险?对于基于greenlet的服务器,我将进一步限制问题:假设资源占用实际上是互斥锁(互斥锁阻塞当前线程,尽管不是当前进程;但现在我们不再处于多线程架构中如果我们使用greenlets ...我错了吗?)。
  • 如果我们不是基于 greenlet 的架构(也不是线程架构):Websockets 是如何在服务器中实现的?

  • 还有一个关于 Django 的问题:
  • 当我不在 View 内且无法直接访问 View 参数时,如何识别当前请求?我有使用 threading.local 识别当前线程的坏习惯。 (填充在自定义中间件中)但当时我没有考虑非线程架构(我的代码很好,只要我可以说“一个请求(暗示)一个线程”)。

  • 这将在一个场景中帮助我:识别当前 request当一个表单称为(我的/自定义)字段的 clean()方法(即根据当前请求根据数据验证值)。但是,如果我有超过 10k 限制的同时请求并使用异步(非线程)方法,则此方法将失败。

    最佳答案

    ( EDIT - gevent.monkey.patch_all() - 在 wsgy.py 脚本文件中运行 - 自动修补 threadlocals 以成为 greenlet locals,因此 GEvent(或 GUnicorn 与 Gevent 工作人员)不需要使用 Werkzeug 的替代方案 -如果不知何故你使用没有 GEvent 的 greenlets,你可能需要这个解决方案 )

    当我想起 Flask Framework 时,我找到了答案。 :

    Flask 是一个框架,它支持“全局”许多对象,如 sessionrequest “看起来”像 threading.local对象。主要区别在于它们是 上下文本地人 而不是线程局部变量,上下文是 任何当前执行堆栈 .

    线程有它自己的上下文(因此在阅读线程理论时会有上下文切换的概念)。一个进程有它的上下文,它包含线程(和一个主线程)。

    到目前为止,在我们所知道的理论中,一个进程包含一个线程,一个线程包含它自己的执行上下文。除非线程可以创建自己的数据上下文,否则数据始终是共享的。这是线程本地(变量/数据)概念出现的地方。

    但是为了解决并发执行的概念,并考虑到 C10K 问题,一个线程中的异步执行是首选,而不是多个阻塞线程和相应的上下文切换(特别是关于 python,我们在默认的 python distr0 中有 GIL)。 Greenlet 被创建为同线程切换上下文,现在层次结构发生了变化:

    Process 1--* thread 1--* greenlet (and now the requests are here)

    所以 Greenlets 的概念是在像 Gevent 这样的服务器中用 Python 创建和实现的,你不能再使用线程本地数据,因为请求不再绑定(bind)到线程(即它们可以是 共享 相同的线程本地上下文,争夺数据)。

    现在上下文本身就是greenlet,我们需要上下文本地而不是线程本地的概念。

    那么:Flask 如何使用本地上下文来隔离每个请求的数据? (例如 session 、请求)。上下文无关隔离的答案在这里:

    Werkzeug's Context Locals

    Werkzeug 和 Flask 具有相同的创建者。 Werkzeug 是 不是 一个框架,但只是 一组可以在任何 WSGI 框架中使用的实用程序 (例如 Django )。框架本身就是 Flask,它实际上依赖于 Werkzeug 的实用程序。

    Werkzeug 的上下文局部变量有助于创建(正确地说)上下文局部变量(上下文表示线程、请求或进程 - 取决于服务器如何分派(dispatch)请求),这可以帮助我们存储特定于 greenlet 的数据并避免使用线程本地化:
    #a python module for my django project where I define
    #a custom field class which statically needs to know the
    #current request.

    #I was using, instead, a threadlocal. The usage is THE SAME.
    #the main difference is that threads are GCed, while contexts
    #not necessarily, so you must ALWAYS release them explicitly
    #using release_local, for the current context.

    #this code below used to have `threading.local` instances
    #instead of `werkzeug.local.Local` instances.

    #as I said before, assigning data works like before, but
    #the main difference is when releasing the data.

    from werkzeug.local import Local, release_local

    class AutocompleteField(object):

    DATA = Local()

    @staticmethod
    def set_request(request):
    AutocompleteField.DATA.request = request

    @staticmethod
    def unset_request(request):
    release_local(AutocompleteField.DATA)

    @staticmethod
    def get_request():
    try:
    return AutocompleteField.DATA.request
    except AttributeError as e:
    return None

    关于django - GEvent/GUnicorn 和 C10k 问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24684781/

    29 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com