如何在uWsgi中实现真正的多处理?

时间:2014-11-14 08:41:51

标签: flask uwsgi

我有一个用Flask编写的python脚本,它需要一些准备工作(连接到数据库,获取一些其他资源等)才能真正接受请求。

我在Apache HTTPD下使用wsgi。 Apache配置:

WSGIDaemonProcess test user=<uid> group=<gid> threads=1 processes=4
WSGIScriptAlias /flask/test <path>/flask/test/data.wsgi process-group=test

它工作正常:Apache将启动4个完全独立的进程,每个进程都有自己的数据库连接。

我现在正试图切换到uwsgi + nginx。 nginx config:

location /flask/test/ {
    include uwsgi_params;
    uwsgi_pass unix:/tmp/uwsgi.sock;
}

uwsgi:

uwsgi -s /tmp/uwsgi.sock --mount /flask/test=test.py --callable app --manage-script-name --processes=4 --master

简化脚本test.py:

from flask import Flask, Response
app = Flask(__name__)


def do_some_preparation():
    print("Prepared!")


@app.route("/test")
def get_test():
    return Response("test")

do_some_preparation()

if __name__ == "__main__":
    app.run()

我期望看到&#34;准备好了!&#34;输出4次。但是,uwsgi没有这样做,输出:

Python main interpreter initialized at 0x71a7b0
your server socket listen backlog is limited to 100 connections
your mercy for graceful operations on workers is 60 seconds
mapped 363800 bytes (355 KB) for 4 cores
*** Operational MODE: preforking ***
mounting test.py on /flask/test
Prepared! <======================================
WSGI app 0 (mountpoint='/flask/test') ready in 0 seconds ...
*** uWSGI is running in multiple interpreter mode ***
spawned uWSGI master process (pid: 1212)
spawned uWSGI worker 1 (pid: 1216, cores: 1)
spawned uWSGI worker 2 (pid: 1217, cores: 1)
spawned uWSGI worker 3 (pid: 1218, cores: 1)
spawned uWSGI worker 4 (pid: 1219, cores: 1)

因此,在这个简化的例子中,uwsgi产生了4个工作者,但只执行了一次do_some_preparation()。在实际应用程序中,打开了几个数据库连接,显然这些连接被这4个进程重用,并导致并发请求出现问题。

有没有办法告诉uwsgi产生几个完全独立的进程?

编辑:当然,我可以使用以下解决方法:

from flask import Flask, Response
app = Flask(__name__)

all_prepared = False

def do_some_preparation():
    global all_prepared
    all_prepared = True
    print("Prepared!")


@app.route("/test")
def get_test():
    if not all_prepared:
        do_some_preparation()
    return Response("test")

if __name__ == "__main__":
    app.run()

但接下来我将不得不放置这个&#34; all_prepared&#34;检查每条路线,这似乎不是一个好的解决方案。

2 个答案:

答案 0 :(得分:6)

默认情况下,uWSGI会进行预先编制。所以你的应用程序加载了一次,然后分叉。

如果您想为每个工作人员加载一次应用程序,请将-lazy-apps添加到uWSGI选项中。

顺便说一句,在这两种情况下,你都处于真正的多处理阶段:)

答案 1 :(得分:3)

好像我自己找到了答案。答案是:我的代码应该重新设计为:

@app.before_first_request
def do_some_preparation():
    ...

然后Flask将分别为每个工作者运行do_some_preparation()函数,允许每个工作者拥有自己的数据库连接(或其他并发不容忍的资源)。