Python中,WSGI,多处理和共享数据(Python, WSGI, multiprocessin

2019-08-01 03:32发布

我有点困惑multiproessing mod_wsgi的特征和有关WSGI应用的通用设计,将WSGI服务器上的多处理能力来执行。

考虑以下指令:

WSGIDaemonProcess example processes=5 threads=1

如果正确地明白的mod_wsgi将产生5的Python(例如CPython的)进程和任何这些方法中的可以接收来自用户的请求。

该文件说:

其中共享数据需要是可见的所有应用程序的情况下,不管它们执行将子进程,以及通过一个应用程序对数据所做的改变将立即提供给另一个,包括在另一个子过程的任何执行时,外部数据存储器中,如一个数据库或共享存储器必须被使用。 在正常的Python模块全局变量不能被用于此目的。

但是,在这种情况下,它会当一个人想以确保应用程序在任何WSGI条件(包括多处理的)运行非常沉重。

例如,其中包含连接的用户的当前量的简单变量 - 它应该是过程安全读/写从/向分布式缓存,或DB或(如果这种外的的标准库的机制是可用的)共享记忆?

并且将在这样的代码

counter = 0

@app.route('/login')
def login():
    ...
    counter += 1
    ...

@app.route('/logout')
def logout():
    ...
    counter -= 1
    ...

@app.route('/show_users_count')
def show_users_count():
    return counter

行为异常的多处理环境?

谢谢!

Answer 1:

有几个方面你的问题需要考虑。

首先,阿帕奇之间MPM的和mod_wsgi的应用程序的交互。 如果你运行在嵌入式模式mod_wsgi的应用程序(不WSGIDaemonProcess需要, WSGIProcessGroup %{GLOBAL} )你继承从Apache MPM的多/多线程。 这应该是最快的选项,你最终不得不每个进程多进程和多线程,这取决于你的MPM的配置。 相反,如果你在守护进程模式下运行的mod_wsgi,与WSGIDaemonProcess <name> [options]WSGIProcessGroup <name> ,你有一个小的成本上多/多线程精细控制开销 。

内的单个的apache2服务器用户还可以定义零个,一个或多个命名WSGIDaemonProcess ES,和每个应用程序可以在这些过程中的一个上运行( WSGIProcessGroup <name> )或与嵌入式模式下运行WSGIProcessGroup %{GLOBAL}

您可以通过检查检查多/多线程wsgi.multithreadwsgi.multiprocess变量。

与您的配置WSGIDaemonProcess example processes=5 threads=1你有5个独立过程,每个具有单个执行线程:没有全局数据,没有共享的存储器,因为你是不是在产卵子过程的控制,但mod_wsgi的是这样做你。 要共享全局状态你已经列出了一些可能的选项:一个DB到您的流程界面,某种形式的文件系统为基础的持久性,守护进程(开始在外面阿帕奇)和基于套接字的IPC。

正如罗兰·斯密所指出的,后者可以使用高级别API通过实施multiprocessing.managers :外Apache下,可以创建和启动BaseManager服务器进程

m = multiprocessing.managers.BaseManager(address=('', 12345), authkey='secret')
m.get_server().serve_forever()

并且里面你Apps,您connect

m = multiprocessing.managers.BaseManager(address=('', 12345), authkey='secret')
m.connect()

上面的例子是假的,因为m有注册没有任何有用的方法,但在这里 (python文档),你会发现如何创建和代理的对象(如counter在你的例子),你的流程之中。

在你的例子最后的评论,与processes=5 threads=1 。 我明白,这只是一个例子,但在现实世界中的应用我猜想,性能会相对于可比的processes=1 threads=5 :你应该进入共享数据的复杂性在多处理器只有在预期的性能提升“单进程多线程的模型是显著。



Answer 2:

从进程和线程的WSGI文档:

当Apache在模式下运行,从而有多个的子进程,每个子进程将包含每个WSGI应用子翻译。

这意味着,在配置中,5个处理与1个线程的每个,将有5个口译和不共享的数据。 您的计数器对象将是唯一的每个翻译。 你会需要或者建立一些定制的解决方案来算会话或,这绝对是我的建议,使用预置的解决方案(谷歌分析和Chartbeat是(你可以用,某种基于持久性解决方案等进行通信的一个共同的过程)梦幻般的选项)。

我倾向于认为使用全局变量作为全球滥用的大形式共享数据。 这是一个错误很好,在大多数环境下的便携性问题,我在做并行处理。如果突然间你的应用程序是在多个虚拟机上运行? 这不管是什么的线程和进程的共享模式破坏你的代码。



Answer 3:

如果使用的是multiprocessing ,有多种方式进程之间共享数据。 价值观和阵列仅当进程有一个父/子关系(他们是在继承共享)工作。 如果不是这种情况,使用ManagerProxy对象。



文章来源: Python, WSGI, multiprocessing and shared data