Redis イベントをサブスクライブする単純な Flask/socketio/eventlet サーバーをまとめようとしています。私が見ている動作は、Flask デバッグが有効になっていると、Werkzeug が変更を検出して socketio を再起動するたびに、別の redis リスナーも開始されるということです (古いリスナーは終了しません)。
すべての socketio ハンドラが削除された作業バージョンを次に示します。
import json
from flask import Flask, render_template
from flask_socketio import SocketIO, emit
from flask.ext.redis import FlaskRedis
import eventlet
eventlet.monkey_patch()
with open('config/flask.json') as f:
config_flask = json.load(f)
app = Flask(__name__, static_folder='public', static_url_path='')
app.config.update(
DEBUG= True,
PROPAGATE_EXCEPTIONS= True,
REDIS_URL= "redis://localhost:6379/0"
)
redis_cache = FlaskRedis(app)
socketio = SocketIO(app)
@app.route('/')
def index():
cache = {}
return render_template('index.html', **cache)
def redisReader():
print 'Starting Redis subscriber'
pubsub = redis_cache.pubsub()
pubsub.subscribe('msg')
for msg in pubsub.listen():
print '>>>>>', msg
def runSocket():
print "Starting webserver"
socketio.run(app, host='0.0.0.0')
if __name__ == '__main__':
pool = eventlet.GreenPool()
pool.spawn(redisReader)
pool.spawn(runSocket)
pool.waitall()
手動の redis-cli パブリッシング (PUBLISH msg himom) を投入します。これにより、次の出力が生成されます。
Starting Redis subscriber
Starting webserver
* Restarting with stat
>>>>> {'pattern': None, 'type': 'subscribe', 'channel': 'msg', 'data': 1L}
Starting Redis subscriber
Starting webserver
* Debugger is active!
* Debugger pin code: 789-323-740
(22252) wsgi starting up on http://0.0.0.0:5000
>>>>> {'pattern': None, 'type': 'subscribe', 'channel': 'msg', 'data': 1L}
>>>>> {'pattern': None, 'type': 'message', 'channel': 'msg', 'data': 'himom'}
>>>>> {'pattern': None, 'type': 'message', 'channel': 'msg', 'data': 'himom'}
Redis リスナーが複数回開始されるのはなぜですか? 変更を加えて保存すると、Werkzeug は毎回別の変更を開始します。これを正しく処理するにはどうすればよいですか?
関連するパッケージとそのバージョンのリストは次のとおりです。
- パイソン 2.7.6
- フラスコ 0.10.1
- Werkzeug 0.11.4
- イベントレット 0.18.4
- グリーンレット 0.4.9
- フラスコ-Redis 0.1.0
- Flask-SocketIO 2.2
** 更新 ** 現在、部分的な解決策があります。プールの動作が Flask の「before_first_request」関数に移動したことを除いて、上記のすべては同じままです。
def setupRedis():
print "setting up redis"
pool = eventlet.GreenPool()
pool.spawn(redisReader)
def runSocket():
print "Starting Webserver"
socketio.run(app, host='0.0.0.0')
if __name__ == '__main__':
app.before_first_request(setupRedis)
print app.before_first_request_funcs
runSocket()
残りの問題は、'before_first_request' が既存の websocket がある場合を処理しないことですが、それは別の問題です。