0

작은 Flask 앱을 작성하여 여러 로그 파일을 인터넷을 통해 브라우저로 스트리밍했습니다. 플라스크 앱으로 여러 개의 로그를 여러 클라이언트에 스트리밍

http://X.X.X.X:9001/stream/test01_base_Baseline/NW 
http://X.X.X.X:9001/stream/test01_base_Baseline/N 

내가 이상한 동작이 : 나는 두 개의 링크를 열 때

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 server:app -k eventlet -b 0.0.0.0:9001 

gunicorn이 응용 프로그램을 실행합니다. 두 스트림 중 하나는 예상대로 작동하지만 두 번째 스트림은 중단되거나 대량으로 스트리밍됩니다. 예를 들어, 첫 번째 페이지에는 매초마다 한 줄씩 표시되고, 두 번째 페이지에는 매 20 초마다 약 15-20 줄이 표시됩니다. 그 행동 또한 일관성이 없습니다. 때로는 첫 번째 페이지가 중단되고 두 번째 페이지는 정기적으로 작동합니다.

저는 웹 개발에 아주 익숙합니다.

편집

나는 훨씬 간단 버전

def read_process(): 
    i = 1 
    while True: 
     payload = 'line' + str(i) 
     i += 1 
     yield "data:" + json.dumps(payload) + "\n\n" 
     sleep(1) 

read_process을 대체하기 위해 노력했다이 버전은 하지이 같은 문제를 havethe 않습니다 내가 예상하는대로 동작합니다. 두 개의 스트림이 함께 수신됩니다.

+0

가능한 한 일찍'eventlet.monkey_patch()'를 실행 해보십시오 - 첫 번째 줄에. 그게 도움이되지 않는다면, 쉘 풀을 쓰레드 풀에 넣으십시오. 'g = eventlet.tpool.Proxy (proc.Group())' – temoto

+0

첫번째 줄에서'eventlet.monkey_patch()'를 움직여도 차이가 없습니다. 두 번째 옵션은 실제로 그것을 더욱 악화시킵니다. 그들은 둘 다 막히고 나는 오류 메시지를 받는다 :'file "/usr/local/lib/python2.7/dist-packages/eventlet/queue.py", 줄 118, switch, self.greenlet.switch (value), 오류 : 다른 스레드로 전환 할 수 없습니다. ' – Rojj

+0

읽기 전용 스레드 풀링을 시도하십시오. 'lines = eventlet.tpool.execute (g.readlines) ' – temoto

답변

0

tail 프로세스에서 더 많은 데이터를 사용할 수있을 때까지 g.readlines() 블록이 발생합니다. 불행히도, 그것은 하나의 녹색 스레드 대신 전체 프로그램을 차단합니다.

tail 과정없이 eventlet.tpool.Proxy(open(log_file, 'rb'))을 사용할 수 있어야합니다.

이것이 실패하면 바로 지금은 별도의 OS 스레드에서 파일 작업을 수행하고 전역 변수를 통해 데이터를주고 로컬 소켓을 통해 해당 변수에 대한 액세스를 동기화하는 것입니다. 나는 그것이 절반 코드를 shelljob에서 반복하고 또 다른 절반을 eventlet.tpool에서 반복하기 때문에 절름발이라는 것을 알고있다. 죄송합니다. 우리는 더 쉽게 해결할 수없는 tpool에 버그가 있습니다.

관련 문제