当前位置:   article > 正文

Python Flask 后端向前端推送信息——轮询、SSE、WebSocket_flask sse

flask sse

简介

后端向前端推送信息,通知任务完成

轮询SSEWebSocket
请求方式HTTPHTTPTCP长连接
触发方式轮询事件事件
优点实现简单易兼容实现简单开发成本低全双工通信,开销小,安全,可扩展
缺点消耗较大不兼容IE传输数据需二次解析,开发成本大
适用场景服务端向客户端单向推送网络游戏、银行交互、支付




安装

pip install flask
  • 1




轮询

main.py

import time
import threading

from flask_cors import CORS
from flask import Flask, redirect

app = Flask(__name__)
cors = CORS(app)

job = {}  # 任务状态


def do_job(id):
    global job
    job[id] = 'doing'
    time.sleep(5)
    job[id] = 'done'


@app.route('/job/<id>', methods=['POST'])
def create(id):
    """创建任务"""
    threading.Thread(target=do_job, args=(id,)).start()
    response = redirect(f'/job/{id}')  # 重定向到查询该任务状态
    return response


@app.route('/job/<id>', methods=['GET'])
def status(id):
    """查询任务状态"""
    return job.get(id, 'not exist')


if __name__ == '__main__':
    app.run()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35

index.html

<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <title>轮询</title>
    <script src="https://cdn.staticfile.org/jquery/3.6.1/jquery.min.js"></script>
</head>
<body>
<button id="create">执行任务</button>
</body>
<script>
    $("#create").click(function () {
        var id = parseInt(Math.random() * 100000000);  // 任务ID
        $.post({
            url: "http://127.0.0.1:5000/job/" + id.toString(),
            success: function (response) {
                $("body").append("<p id='p" + id.toString() + "'>任务" + id.toString() + ":created</p>");
                var interval = setInterval(function () {
                    $.get({
                        url: "http://127.0.0.1:5000/job/" + id.toString(),
                        success: function (response) {
                            console.log(response);
                            $("#p" + id.toString()).text("任务" + id.toString() + ":" + response)
                            if (response === 'done') {
                                clearInterval(interval);
                            }
                        }
                    });
                }, 1000);
            }
        });
    });
</script>
</html>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

效果

请添加图片描述




SSE

需要异步启动 + Redis

gunicorn 无法在 Windows 上运行,WSL 对 gevent 支持不友好,建议在纯 Linux 系统下使用

安装 Redis

sudo apt update
sudo apt install redis-server
  • 1
  • 2

安装

pip install flask-sse gunicorn gevent
  • 1

sse.py

from flask import Flask, render_template

from flask_sse import sse
from flask_cors import CORS

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


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


@app.route('/hello')
def publish_hello():
    sse.publish({'message': 'Hello!'}, type='greeting')
    return 'Message sent!'
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

templates/index.html

<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <title>SSE</title>
    <script src="https://cdn.staticfile.org/jquery/3.6.1/jquery.min.js"></script>
</head>
<body>
<h1>Flask-SSE Quickstart</h1>
<script>
    var source = new EventSource("stream");
    source.addEventListener("greeting", function (event) {
        var data = JSON.parse(event.data);
        console.log(data.message)
        $("body").append("<p>" + data.message + "</p>");
    }, false);
    source.addEventListener("error", function (event) {
        console.log("Failed to connect to event stream. Is Redis running?");
    }, false);
</script>
</body>
</html>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

启动

gunicorn sse:app --worker-class gevent --bind 127.0.0.1:8000
  • 1

nginx 配置

location ^~ /sse/ {
    proxy_pass http://127.0.0.1:8000/;
    proxy_set_header Connection '';
    proxy_http_version 1.1;
    chunked_transfer_encoding off;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

效果




WebSocket

异步启动,eventlet 性能最好,然后是 gevent

安装

pip install flask-socketio gunicorn eventlet
  • 1

pip install flask-socketio gunicorn gevent-websocket
  • 1

main.py

from flask_socketio import SocketIO
from flask import Flask, render_template, request

app = Flask(__name__)
socketio = SocketIO(app, cors_allowed_origins='*')
connected_sids = set()  # 存放已连接的客户端


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


@socketio.on('connect')
def on_connect():
    connected_sids.add(request.sid)
    print(f'{request.sid} 已连接')


@socketio.on('disconnect')
def on_disconnect():
    connected_sids.remove(request.sid)
    print(f'{request.sid} 已断开')


@socketio.on('message')
def handle_message(message):
    """收消息"""
    data = message['data']
    print(f'{request.sid} {data}')


@app.route('/hello', defaults={'sid': None})
@app.route('/hello/<sid>')
def hello(sid):
    """发消息"""
    if sid:
        if sid in connected_sids:
            socketio.emit('my_response', {'data': f'Hello, {sid}!'}, room=sid)
            return f'已发信息给{sid}'
        else:
            return f'{sid}不存在'
    else:
        socketio.emit('my_response', {'data': 'Hello!'})
        return '已群发信息'


if __name__ == '__main__':
    socketio.run(app)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49

templates/index.html

<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <title>WebSocket</title>
    <script src="https://cdn.staticfile.org/jquery/3.6.1/jquery.min.js"></script>
    <script src="https://cdn.staticfile.org/socket.io/4.5.2/socket.io.min.js"></script>
</head>
<body>
<h1>Flask-SocketIO Quickstart</h1>
<h2 id="sid">客户端</h2>
<h2>发消息</h2>
<input id="emit_data" value="Hello World!">
<button id="emit">发消息</button>
<h2>收消息</h2>
<div id="log"></div>
<script>
    var socket = io();
    // var socket = io("ws://127.0.0.1:5000");

    socket.on("connect", function () {
        $("#sid").text("客户端:" + socket.id)
    });

    $("#emit").click(function () {
        socket.emit("message", {data: $("#emit_data").val()});
    });  // 点击按钮发消息

    socket.on("my_response", function (msg) {
        $("#log").append("<p>" + msg.data + "</p>");  // 收消息
    });
</script>
</body>
</html>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

效果

更多内容查阅官方示例

WebSocekt 是 HTML5 规范的一部分,是一种应用层协议,借鉴了 socket 思想,为客户端和服务端之间提供了双向通信功能,包含一套标准的 API。


Socket.IO 是一个 JavaScript 库,不仅支持 WebSocket,还支持许多种轮询机制,当 Socket.IO 检测到当前环境不支持 WebSocket 时,能自动选择最佳方式实现网络实时通信。


后端 Flask-Sockets 对应前端使用原生 WebSocekt
后端 Flask-SocketIO 对应前端使用 Socket.IO(推荐这种)




事件

  • error:
  • reconnect:
  • reconnect_attempt:
  • reconnect_error:
  • reconnect_failed:
  • ping:
  • connect:
  • disconnect:
  • connect_error:




参考文献

  1. Flask-SSE Documentation
  2. Flask-SocketIO Documentation
  3. 长连接/websocket/SSE等主流服务器推送技术比较
  4. Server-Sent Events 与 WebSocket 的比较
  5. 七牛云CDN
  6. js停止setInterval的方法与setInterval循环执行的注意事项
  7. Python flaks-sse 库的简单测试
  8. Ubuntu用命令行打开网页的三种方法
  9. 如何使用W3M从Linux终端浏览
  10. 3种 Linux 命令行中使用的 Web 浏览器
  11. EventSource / Server-Sent Events through Nginx
  12. Server-Sent Events connection timeout on Node.js via Nginx
  13. Flask教程(十九)SocketIO
  14. flask-socketio笔记
  15. websocket在线测试
  16. WebSocket 教程 - 阮一峰的网络日志
  17. 手摸手教你使用WebSocket
  18. Web端即时通讯技术盘点:短轮询、Comet、Websocket、SSE
  19. Client API | Socket.IO
  20. WebSocket 与 Socket.IO
  21. WebSocket - Web API 接口参考 | MDN
  22. 在flask上使用websocket
  23. WebSocket详解(一):初步认识WebSocket技术
  24. Flask:使用SocketIO实现WebSocket与前端Vue进行实时推送
  25. Flask使用flask_socketio将信息时时推送前台
  26. 使用 Flask-SocketIO 实现私聊:通过flask-socketio中的sid给指定的客户端发送消息,对方接收不到
  27. Flask route parameters default values
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小丑西瓜9/article/detail/389302
推荐阅读
相关标签
  

闽ICP备14008679号