2014-11-14 3 views
2

Flask로 작성된 python 스크립트가 있습니다. 실제로는 요청을 받아들이 기 전에 준비 작업 (데이터베이스에 연결하고 다른 리소스를 확보하는 등)이 필요합니다.uWsgi에서 진정한 멀티 프로세싱을 달성하는 방법은 무엇입니까?

나는 wsgi가있는 Apache HTTPD에서 사용하고있었습니다. Apache config :

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를 설정 :

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() 

내가 기대하는 것은 보는 것입니다 출력에서 4 번.

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()을 실행 : 그러나 uwsgi 출력이, 그렇게하지 않습니다. 실제 응용 프로그램에서는 여러 개의 데이터베이스 연결이 열려 있으며 이러한 연결은 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() 

그러나 나는 이것이 좋은 아닌 것 같아 모든 경로로 확인 "all_prepared"배치 할 것이다 : 나는, 물론,이 같은 문제를 해결 작업을 얻을 수 해결책.

답변

2

내가 직접 답변을 찾은 것 같습니다. 그리고 대답은 : 내 코드는 다음과 같이 재 설계되어 있어야합니다 :

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

그런 다음 플라스크가 자신의 데이터베이스 연결 (또는 다른 동시성 관용 자원을 가지고 각각을 개별적으로 각각의 작업자 do_some_preparation() 기능을 실행 허용 돌볼 것).

+1

+1 나는 비슷한 대답을 게시하려고합니다. –

4

기본적으로 uWSGI는 프리 포킹을 수행합니다. 따라서 앱이 한 번로드 된 다음 분기됩니다.

작업자 당 응용 프로그램을 한 번로드하려면 --lazy-apps를 uWSGI 옵션에 추가하십시오.

두 경우 모두에서 당신은 진정한 멀티 프로세싱 중입니다. :)

관련 문제