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

标签 python multiprocessing mod-wsgi wsgi

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

考虑以下指令:

WSGIDaemonProcess example processes=5 threads=1

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

文档说:

Where shared data needs to be visible to all application instances, regardless of which child process they execute in, and changes made to the data by one application are immediately available to another, including any executing in another child process, an external data store such as a database or shared memory must be used. Global variables in normal Python modules cannot be used for this purpose.

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

例如,一个包含当前连接用户数量的简单变量 - 它应该是进程安全的从 memcached 读/写到 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

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

谢谢!

最佳答案

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

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

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

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

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

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

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

在你的应用程序中,你 connect :

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

上面的例子是假的,因为 m没有注册有用的方法,但是 here (python 文档)您将了解如何在您的进程中创建和代理一个对象(如示例中的 counter)。

对您的示例的最后评论,带有 processes=5 threads=1 .我知道这只是一个示例,但在实际应用中,我怀疑性能与 processes=1 threads=5 相当。 :只有在“单进程多线程”模型的预期性能提升显着的情况下,您才应该了解在多处理中共享数据的复杂性。

关于Python、WSGI、多处理和共享数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12715139/

相关文章:

python - 通过多处理减少内存占用?

python - 仅当从 mod_wsgi 运行时才出现来自 Selenium firefox_binary.py 的 WebDriverException

python - 使用 mod_wsgi 运行 wsgi 应用程序时惨遭失败

multithreading - 在指定数量的内核上运行MPI程序

Django - 根据服务器从 wsgi 引用不同的设置文件

python - 两个二维数组从哪里开始相互重叠?

python - 使用 GUI 执行 ping 命令

python - 在 Python 中计算 CSV 中的每月总值

python - 如何在字符串中大写偶数字母和小写奇数字母?

python - 共享非连续访问 Numpy 数组