我有点困惑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
行为异常的多处理环境?
谢谢!
有几个方面你的问题需要考虑。
首先,阿帕奇之间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.multithread
和wsgi.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
:你应该进入共享数据的复杂性在多处理器只有在预期的性能提升“单进程多线程的模型是显著。
从进程和线程的WSGI文档:
当Apache在模式下运行,从而有多个的子进程,每个子进程将包含每个WSGI应用子翻译。
这意味着,在配置中,5个处理与1个线程的每个,将有5个口译和不共享的数据。 您的计数器对象将是唯一的每个翻译。 你会需要或者建立一些定制的解决方案来算会话或,这绝对是我的建议,使用预置的解决方案(谷歌分析和Chartbeat是(你可以用,某种基于持久性解决方案等进行通信的一个共同的过程)梦幻般的选项)。
我倾向于认为使用全局变量作为全球滥用的大形式共享数据。 这是一个错误很好,在大多数环境下的便携性问题,我在做并行处理。如果突然间你的应用程序是在多个虚拟机上运行? 这不管是什么的线程和进程的共享模式破坏你的代码。
如果使用的是multiprocessing
,有多种方式进程之间共享数据。 价值观和阵列仅当进程有一个父/子关系(他们是在继承共享)工作。 如果不是这种情况,使用Manager
和Proxy
对象。