Python,WSGI,多处理和共享数据

Zau*_*bov 23 python mod-wsgi wsgi multiprocessing

我对mod_wsgi的多重管理功能以及将在具有多处理能力的WSGI服务器上执行的WSGI应用程序的一般设计感到困惑.

请考虑以下指令:

WSGIDaemonProcess example processes=5 threads=1
Run Code Online (Sandbox Code Playgroud)

如果我理解正确,mod_wsgi将生成5个Python(例如CPython)进程,并且这些进程中的任何一个都可以接收来自用户的请求.

文件说:

共享数据需要对所有应用程序实例可见,无论它们执行哪个子进程,并且一个应用程序对数据所做的更改都可以立即供另一个应用程序使用,包括在另一个子进程中执行的任何子进程,外部数据存储,如必须使用数据库或共享内存.普通Python模块中的全局变量不能用于此目的.

但是在这种情况下,当想要确定应用程序在任何WSGI条件(包括多处理条件)中运行时,它会变得非常沉重.

例如,一个包含当前连接用户数量的简单变量 - 它应该是从/向memcached进行过程安全读/写,还是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
Run Code Online (Sandbox Code Playgroud)

在多处理环境中表现不可预测?

谢谢!

Ste*_*o M 22

您的问题需要考虑几个方面.

首先,apache MPM和mod_wsgi应用程序之间的交互.如果以嵌入模式运行mod_wsgi应用程序(WSGIDaemonProcess不需要WSGIProcessGroup %{GLOBAL}),则从apache MPM继承多处理/多线程.这应该是最快的选项,并且每个进程最终会有多个进程和多个线程,具体取决于您的MPM配置.相反,如果您在守护进程模式下运行mod_wsgi,使用WSGIDaemonProcess <name> [options]WSGIProcessGroup <name>,您可以很好地控制多处理/多线程,但代价是开销很小.

在单个apache2服务器中,您可以定义零个,一个或多个命名WSGIDaemonProcesses,并且每个应用程序可以在其中一个进程中WSGIProcessGroup <name>运行()或以嵌入模式运行WSGIProcessGroup %{GLOBAL}.

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

使用您的配置,WSGIDaemonProcess example processes=5 threads=1您有5个独立的进程,每个进程都有一个执行线程:没有全局数据,没有共享内存,因为您无法控制产生子进程,但mod_wsgi正在为您执行此操作.要共享一个全局状态,您已经列出了一些可能的选项:您的进程所连接的数据库,某种基于文件系统的持久性,守护进程(在apache之外启动)和基于套接字的IPC.

正如Roland Smith所指出的,后者可以通过以下方式使用高级API实现multiprocessing.managers:您创建并启动BaseManager服务器进程的外部apache

m = multiprocessing.managers.BaseManager(address=('', 12345), authkey='secret')
m.get_server().serve_forever()
Run Code Online (Sandbox Code Playgroud)

在你的应用内你connect:

m = multiprocessing.managers.BaseManager(address=('', 12345), authkey='secret')
m.connect()
Run Code Online (Sandbox Code Playgroud)

上面的示例是虚拟的,因为m没有注册有用的方法,但是在这里(python docs),您将找到如何在您的进程中创建和代理对象(如counter示例中所示).

最后评论你的例子,用processes=5 threads=1.我知道这只是一个例子,但在现实世界的应用程序中,我怀疑性能将与以下方面相媲美processes=1 threads=5:只有当预期性能提升超过"单个进程多线程"时,才应该进入多处理中共享数据的复杂性模型很重要.