0

小さなFlaskアプリを書いて、複数のログファイルをインターネット経由でブラウザにストリーミングしました。複数のログを複数のクライアントにストリーミングする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 server:app -k eventlet -b 0.0.0.0:9001 

コマンドでgunicornで、このアプリを実行します。

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

を、私は奇妙な行動を持っています。 2つのストリームのうち1つは期待どおりに動作しますが、2つ目のストリームはハングするかバルクでストリーミングされます。たとえば、最初のページでは1秒間に1行ずつ、2ページ目には20秒ごとに15〜20行程度が表示されます。この振る舞いも一貫していません。ときには、最初のページがハングし、2番目が定期的に動作します。

私はウェブ開発にかなり新しいです。

EDIT

は、私は非常に簡単なバージョン

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と私は期待通りに動作しません。 2つのストリームは一緒に受信されます。

+0

できるだけ早く 'eventlet.monkey_patch()'を実行してください - 最初の行にしてください。それでも問題が解決しない場合は、shelljobをスレッドプールにオフロードしてみてください。 '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

g.readlines()ブロックは、より多くのデータがtailプロセスから入手可能になるまで、ブロックされます。残念ながら、1つの緑色のスレッドの代わりに全プログラムをブロックしています。

eventlet.tpool.Proxy(open(log_file, 'rb'))tailプロセスなしで使用できるようにする必要があります。

これで失敗した場合は、別のOSスレッドでファイル操作を行い、グローバル変数を介してデータを通信し、ローカルソケットを介して前記変数へのアクセスを同期させることです。私はそれがshelljobからの半分のコードと、もう1つの半分をeventlet.tpoolから繰り返すので、それが不自由だと分かります。申し訳ありませんが、簡単な解決策が得られないtpoolにバグがあります。

関連する問題