0

我编写了一个小Flask应用程序来通过 Internet 将多个日志文件流式传输到浏览器。

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)

此版本没有相同的问题,并且行为与我预期的一样。两个流一起接收。

4

1 回答 1

0

g.readlines()在进程中有更多数据可用之前,正在发生的事情会阻塞tail。不幸的是,它阻塞了整个程序而不是一个绿色线程。

应该可以eventlet.tpool.Proxy(open(log_file, 'rb'))不用tail处理就可以使用。

如果失败,现在下一个最佳选择是在单独的操作系统线程中执行文件操作,并通过全局变量通信数据,并通过本地套接字同步对所述变量的访问。我知道这很蹩脚,因为它重复了一半的代码shelljob和另一半eventlet.tpool。抱歉,我们在 tpool 中有一个错误,它阻止了更简单的解决方案。

于 2017-11-17T01:47:37.017 回答