我想在我的应用程序中实现服务器端事件。我正在使用带有gevent后端的Flask。我主要遵循官方snippet,有两个重要的区别:
multiprocessing.Process
的实例)生成,而不是gevent.spawn
。它发送"内部"事件QueueHandler
来自logutils
这是一个最小的例子:
from flask import Flask, Response
import time
import logging
from gevent.wsgi import WSGIServer
from gevent.queue import Queue
import multiprocessing as mp
from logutils.queue import QueueHandler
app = Flask(__name__)
logger = logging.getLogger('events')
logger.setLevel(logging.INFO)
@app.route("/publish")
def publish():
logger = logging.getLogger('events')
def notify():
time.sleep(1)
logger.info('inner')
logger.info('outer')
p = mp.Process(target=notify)
p.start()
return "OK"
@app.route("/subscribe")
def subscribe():
def gen():
logger = logging.getLogger("events")
q = Queue()
handler = QueueHandler(q)
logger.addHandler(handler)
while True:
result = q.get().message
yield result
return Response(gen(), mimetype="text/event-stream")
if __name__ == "__main__":
root = logging.getLogger()
root.addHandler(logging.StreamHandler())
root.setLevel(logging.INFO)
app.debug = True
server = WSGIServer(("", 5000), app)
server.serve_forever()
问题是,StreamHandler
同时捕获"内部"和"外部"事件并将它们记录到stdout。另一方面,QueueHandler
仅推动"外部"事件到队列,所以它无法捕捉"内部"事件,起源于其他过程。
现在,如果我使用multiprocessing.Queue
代替gevent.queue
,那么" / subscribe"路线块。如果我将标准werkzeug服务器(带有线程)与multiprocessing.Queue
结合使用,则上面的代码按预期工作。
发生了什么以及如何解决这个问题?