组件
>具有thread-safe queue的Flask应用程序.
> GET调用返回队列大小.
> POST调用向队列中添加一个元素.
>后台线程打印队列大小
问题
当应用程序是从shell使用python tester.py时,我得到预期的结果:
2014-06-07 14:20:50.677995 Queue size is: 0 127.0.0.1 - - [07/Jun/2014 14:20:51] "POST /addMessage/X HTTP/1.1" 200 - 2014-06-07 14:20:51.679277 Queue size is: 1 2014-06-07 14:20:52.680425 Queue size is: 1 2014-06-07 14:20:53.681566 Queue size is: 1 2014-06-07 14:20:54.682708 Queue size is: 1 127.0.0.1 - - [07/Jun/2014 14:20:55] "POST /addMessage/Y HTTP/1.1" 200 - 2014-06-07 14:20:55.687755 Queue size is: 2 2014-06-07 14:20:56.688867 Queue size is: 2
但是,当使用uwsgi执行应用程序时,我在日志中得到以下内容:
2014-06-07 14:17:42.056863 Queue size is: 0 2014-06-07 14:17:43.057952 Queue size is: 0 [pid: 9879|app: 0|req: 6/6] 127.0.0.1 () {24 vars in 280 bytes} [Sat Jun 7 14:17:43 2014] POST /addMessage/X => generated 16 bytes in 0 msecs (HTTP/1.1 200) 2 headers in 71 bytes (1 switches on core 0) 2014-06-07 14:17:44.059037 Queue size is: 0 2014-06-07 14:17:45.060118 Queue size is: 0 [pid: 9879|app: 0|req: 7/7] 127.0.0.1 () {24 vars in 280 bytes} [Sat Jun 7 14:17:45 2014] POST /addMessage/X => generated 16 bytes in 0 msecs (HTTP/1.1 200) 2 headers in 71 bytes (1 switches on core 0) 2014-06-07 14:17:46.061205 Queue size is: 0 2014-06-07 14:17:47.062286 Queue size is: 0
当在uwsgi下运行时,后台线程看不到与应用程序相同的队列.这是为什么?我怎么能让这两个线程看同一个Queue对象?
更新
>即使将其作为Python脚本执行,我也看到不一致的行为:有时它不会记录消息(使用app.logger),我只能看到打印.这意味着线程正在运行,但它不能与app.logger做任何事情.
uwsgi .ini配置
[uwsgi] http-socket = :9002 plugin = python wsgi-file = /home/ubuntu/threadtest-uwsgi.py enable-threads = true workers = 1 chdir = /home/ubuntu/thread-tester/thread_tester
码
from flask import Flask,jsonify import Queue from threading import Thread import time import datetime import logging import sys logging.basicConfig(stream=sys.stderr,format='%(asctime)s %(levelname)s - %(message)s') app = Flask(__name__) messages = Queue.Queue() def print_queue_size(): while True: app.logger.debug("%s Queue size is: %d" % (datetime.datetime.now(),messages.qsize())) time.sleep(1) t = Thread(target=print_queue_size,args=()) t.setDaemon(True) t.start() @app.route("/queueSize",methods=["GET"]) def get_queue_size(): return jsonify({"qsize": messages.qsize()}),200 @app.route("/addMessage/<message>",methods=["POST"]) def add_message_to_queue(message): messages.put(message) return jsonify({"qsize": messages.qsize()}),200 if __name__ == "__main__": app.run(port=6000)
解决方法
uWSGI tries to (ab)use the Copy On Write semantics of the
fork()
call whenever possible. By default it will fork after having loaded your applications to share as much of their memory as possible. If this behavior is undesirable for some reason,use thelazy
option. This will instruct uWSGI to load the applications after each worker’s fork(). Lazy mode changes the way graceful reloading works: instead of reloading the whole instance,each worker is reloaded in chain. If you want “lazy app loading”,but want to maintain the standard uWSGI reloading behavIoUr,starting from 1.3 you can use thelazy-apps
option.
您的Flask应用程序在uWSGI启动时启动,然后分配一个工作进程.在分叉时,队列对象为空,不再与原始进程共享.线没有走.
尝试设置lazy-apps
option以延迟加载Flask应用程序,直到工作人员启动.