Подтвердить что ты не робот

Как реализовать загрузку сервера в фляге?

Я пытаюсь создать небольшой сайт с функциональностью push-сервера на микро-веб-инфраструктуре Flask, но я не знал, есть ли инфраструктура для работы напрямую.

Я использовал Juggernaut, но, похоже, он не работает с redis-py в текущей версии, и Juggernaut недавно устарела.

У кого-нибудь есть предложение с моим делом?

4b9b3361

Ответ 1

Посмотрите События, отправленные сервером. События, отправленные сервером, являются API браузера, который позволяет вам открывать сокет на ваш сервер, подписываясь на поток обновлений. Для получения дополнительной информации читайте Alex MacCaw (Автор Juggernaut) на почему он убивает juggernaut и почему более простой События, отправленные сервером, в тяжелых случаях - лучший инструмент для работы, чем WebSockets.

Протокол очень прост. Просто добавьте mimetype text/event-stream к вашему ответ. Браузер будет поддерживать соединение открытым и слушать обновления. Мероприятие отправленный с сервера, представляет собой строку текста, начинающуюся с data: и следующей строки новой строки.

data: this is a simple message
<blank line>

Если вы хотите обмениваться структурированными данными, просто сбрасывайте свои данные как json и отправляйте json через провод.

Преимущество состоит в том, что вы можете использовать SSE в Flask без необходимости в дополнительном Сервер. В github есть простой пример чат-приложения, который использует redis как паб/вспомогательный сервер.

def event_stream():
    pubsub = red.pubsub()
    pubsub.subscribe('chat')
    for message in pubsub.listen():
        print message
        yield 'data: %s\n\n' % message['data']


@app.route('/post', methods=['POST'])
def post():
    message = flask.request.form['message']
    user = flask.session.get('user', 'anonymous')
    now = datetime.datetime.now().replace(microsecond=0).time()
    red.publish('chat', u'[%s] %s: %s' % (now.isoformat(), user, message))


@app.route('/stream')
def stream():
    return flask.Response(event_stream(),
                          mimetype="text/event-stream")

Вам не нужно использовать gunicron для запуска пример приложения. Просто выполняйте потоки при запуске приложения, потому что в противном случае SSE-соединение заблокирует ваш сервер разработки:

if __name__ == '__main__':
    app.debug = True
    app.run(threaded=True)

На стороне клиента вам просто нужна функция обработчика Javascript, которая будет вызываться, когда новый сообщение выводится с сервера.

var source = new EventSource('/stream');
source.onmessage = function (event) {
     alert(event.data);
};

Отправленные сервером события поддерживаются в последних браузерах Firefox, Chrome и Safari. Internet Explorer пока не поддерживает события Server-Sent, но ожидается, что они будут поддерживать их в Версия 10. Для поддержки старых браузеров существуют два рекомендованных полифайла.

Ответ 2

В качестве продолжения ответа @peter-hoffmann я написал расширение Flask специально для обработки событий, отправленных сервером. Он назывался Flask-SSE, а доступен в PyPI. Чтобы установить его, запустите:

$ pip install flask-sse

Вы можете использовать его следующим образом:

from flask import Flask
from flask_sse import sse

app = Flask(__name__)
app.config["REDIS_URL"] = "redis://localhost"
app.register_blueprint(sse, url_prefix='/stream')

@app.route('/send')
def send_message():
    sse.publish({"message": "Hello!"}, type='greeting')
    return "Message sent!"

И чтобы подключиться к потоку событий из Javascript, он работает следующим образом:

var source = new EventSource("{{ url_for('sse.stream') }}");
source.addEventListener('greeting', function(event) {
    var data = JSON.parse(event.data);
    // do what you want with this data
}, false);

Документация доступна на ReadTheDocs. Обратите внимание, что вам понадобится работающий Redis для обработки pub/sub.

Ответ 3

Redis лишний: используйте серверные события

Поздно к вечеринке (как обычно), но ИМХО использование Redis может быть излишним.

Пока вы работаете в Python + Flask, рассмотрите возможность использования функций генератора, как описано в этой превосходной статье Panisuan Joe Chasinga. Суть этого заключается в:

В вашем клиенте index.html

var targetContainer = document.getElementById("target_div");
var eventSource = new EventSource("/stream")
  eventSource.onmessage = function(e) {
  targetContainer.innerHTML = e.data;
};
...
<div id="target_div">Watch this space...</div>

На вашем сервере Flask:

def get_message():
    '''this could be any function that blocks until data is ready'''
    time.sleep(1.0)
    s = time.ctime(time.time())
    return s

@app.route('/')
def root():
    return render_template('index.html')

@app.route('/stream')
def stream():
    def eventStream():
        while True:
            # wait for source data to be available, then push it
            yield 'data: {}\n\n'.format(get_message())
    return Response(eventStream(), mimetype="text/event-stream")