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

mis*_*hik 2 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
Run Code Online (Sandbox Code Playgroud)

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

我现在正试图切换到uwsgi + nginx.nginx配置:

location /flask/test/ {
    include uwsgi_params;
    uwsgi_pass unix:/tmp/uwsgi.sock;
}
Run Code Online (Sandbox Code Playgroud)

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()
Run Code Online (Sandbox Code Playgroud)

我期待的是看到"准备好了!" 输出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)
Run Code Online (Sandbox Code Playgroud)

所以,在这个简化的例子中,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()
Run Code Online (Sandbox Code Playgroud)

但是我必须将这个"all_prepared"检查放入每条路线,这似乎不是一个好的解决方案.

rob*_*rto 6

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

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

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