我编写了一个小型Flask
应用,可通过互联网将多个日志文件流式传输到浏览器。
import json
import os
import re
import flask
from shelljob import proc
import eventlet
eventlet.sleep()
eventlet.monkey_patch()
app = flask.Flask(__name__)
@app.route( '/stream/<string:case_name>/<string:wind_dir>' )
def stream(case_name, wind_dir):
g = proc.Group()
foamrun = os.environ["FOAM_RUN"]
foamcase = os.path.join(foamrun, case_name, wind_dir)
log_file = os.path.join(foamcase, 'logs', 'run.log')
print log_file
p = g.run( [ "tail", "-f", log_file ] )
def read_process():
while g.is_pending():
lines = g.readlines()
for proc, line in lines:
# process line and create payload
yield "data:" + json.dumps(payload) + "\n\n"
return flask.Response( read_process(), mimetype='text/event-stream' )
@app.after_request
def after_request(response):
response.headers.add('Access-Control-Allow-Origin', '*')
response.headers.add('Access-Control-Allow-Headers', 'Content-Type,Authorization')
response.headers.add('Access-Control-Allow-Methods', 'GET')
return response
if __name__ == "__main__":
foamrun = os.environ["FOAM_RUN"]
app.run(threaded=True, host='0.0.0.0', port=9001)
我用gunicorn
使用命令
gunicorn server:app -k eventlet -b 0.0.0.0:9001
当我打开两个链接时:
http://X.X.X.X:9001/stream/test01_base_Baseline/NW
http://X.X.X.X:9001/stream/test01_base_Baseline/N
我有一种奇怪的行为。两个流中的一个按预期工作,但第二个流挂起或以批量传输。例如,在第一页上我每秒接收一行,而在第二页上我每20秒左右收到大约15-20行。行为也不一致。有时它是第一个挂起的页面,第二个页面经常出现。
我对网络开发很陌生。
修改
我尝试用更简单的版本替换read_process
def read_process():
i = 1
while True:
payload = 'line' + str(i)
i += 1
yield "data:" + json.dumps(payload) + "\n\n"
sleep(1)
此版本不具有相同的问题并且行为与我预期的一样。两个流一起收到。
答案 0 :(得分:0)
在g.readlines()
进程提供更多数据之前,tail
阻止发生了什么。不幸的是,它阻止了整个程序,而不是一个绿色线程。
应该可以在没有eventlet.tpool.Proxy(open(log_file, 'rb'))
进程的情况下使用tail
。
如果失败,现在的下一个最佳选择是在单独的OS线程中进行文件操作,并通过全局变量传递数据,并通过本地套接字同步对所述变量的访问。我知道这是蹩脚的,因为它重复了shelljob
的一半代码和eventlet.tpool
的另一半代码。抱歉,我们在tpool中有一个错误,可以防止更简单的解决方案。