flask + redis 实现Server-Sent Event demo

本文介绍Web即时通讯原理及实现方法,包括轮询、长轮询、Server-Sent Events (SSE) 和 WebSocket 技术,并通过一个使用 Flask、Redis 和 jQuery 的实时时间展示示例来演示如何实现客户端与服务器之间的双向通信。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

学习要点:
(1)web即时通讯
Web 即时通信,就是说我们可以通过一种机制在网页上立即通知用户一件事情的发生,是不需要用户刷新网页的。
常用的有Polling,Long-Polling,Server Send Event,WebSocket
Server Send Event协议:
HTTP 的头部Content-Type设置成text/event-stream就可以了。其实SSE,就是浏览器向服务器发送一个 HTTP 请求,然后服务器不断单向地向浏览器推送”信息”,这些信息的格式也非常简单,就是前缀data:加上发送的数据内容,然后以\n\n结尾。

(2)redis的订阅分发功能
Redis 发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息
参考:http://www.runoob.com/redis/redis-pub-sub.html

功能:
一个点击button获取当前时间的demo
这里写图片描述

技术栈:
jQuery,flask, redis

分析:
点击button,触发事件 —-> jquery 的post方法发送url为/post,method为POST 的请求 —->/post视图函数执行,redis向time频道publish当前时间—->/stream视图函数监听time频道获得数据,转发给js中的事件源var source = new EventSource(‘/stream’);—–>最后通过innerHTML方法打印到网页

代码:
Python2/3均可

import datetime
import flask
import redis


app = flask.Flask(__name__)
app.secret_key = 'asdf'
red = redis.StrictRedis(host='localhost', port=6379, db=6)


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

@app.route('/post', methods=['POST'])
def post():
    now = datetime.datetime.now().replace(microsecond=0).time()
    red.publish('time', u'%s' % (now.isoformat()))
    return flask.Response(status=204)


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


@app.route('/')
def home():
    return u"""
        <!doctype html>
        <title>chat</title>
        <script src="http://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script>
        <style>body { max-width: 500px; margin: auto; padding: 1em; background: black; color: #fff; font: 16px/1.6 menlo, monospace; }</style>
        </p><button id="time">Click for time!</button>
        <pre id="out"></pre>
        <script>
            function sse() {
                var source = new EventSource('/stream');
                var out = document.getElementById('out');
                source.onmessage = function(e) {
                    out.innerHTML = 'now-tiem:'+ e.data + '\\n' + out.innerHTML;
                };
            }
            $('#time').click(function(){
                    $.post('/post');
                }
            );
            sse();
        </script>
    """ 


if __name__ == '__main__':
    app.debug = True
    app.run(threaded=True)
### FlaskRedis及MySQL集成的教程和文档 #### 集成概述 Flask 是一种轻量级的 Python Web 框架,而 Redis 和 MySQL 则分别提供了缓存服务和关系型数据库支持。通过将这些技术结合起来,可以构建高效、可扩展的应用程序。 #### 使用 Redis 的原因 Redis 可以用来存储会话数据、缓存查询结果以及实现消息队列等功能。这种设计能够显著提高应用性能[^1]。 #### 安装依赖项 为了使 Flask 应用能与 Redis 和 MySQL 进行交互,需先安装必要的库: ```bash $ pip install flask sqlalchemy pymysql redis flask-session ``` 上述命令中包含了 `sqlalchemy`(ORM 工具)、`pymysql`(MySQL 数据库驱动)、`redis`(客户端库)以及 `flask-session`(用于管理基于 Redis 的会话)。 #### 配置 MySQL 数据库连接 在 Flask 中可以通过 SQLAlchemy 来简化对 MySQL 数据库的操作。下面展示如何设置数据库 URI 并将其赋值给环境变量: ```python import os from flask import Flask from flask_sqlalchemy import SQLAlchemy app = Flask(__name__) app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://username:password@localhost/db_name' db = SQLAlchemy(app) class User(db.Model): id = db.Column(db.Integer, primary_key=True) username = db.Column(db.String(80), unique=True, nullable=False) email = db.Column(db.String(120), unique=True, nullable=False) @app.route('/') def index(): users = User.query.all() return str(users) ``` 此代码片段定义了一个简单的模型类 `User` 并展示了如何从表中检索记录[^3]。 #### 整合 Redis 缓存机制 引入 Redis 后,我们可以利用其快速读写特性来减少频繁访问数据库的需求。这里提供一段示例说明如何配置 Redis 作为后端存储 session 数据的方法之一: ```python from flask_session import Session app.config["SESSION_TYPE"] = "redis" app.config["SESSION_PERMANENT"] = False app.config["SESSION_USE_SIGNER"] = True app.config["SESSION_REDIS"] = redis.from_url("redis://localhost:6379") Session(app) ``` 以上脚本设置了使用 Redis 存储 sessions,并启用了签名功能以增强安全性. #### 实际应用场景举例 假设有一个博客系统需要显示文章列表页面,在高并发情况下直接查询 MySQL 性能可能会下降。此时就可以考虑把热门文章的数据放入 Redis 缓存起来,只有当数据发生变化时才更新到 Redis 中去。 ```python cache = redis.StrictRedis(host='localhost', port=6379, decode_responses=True) @app.route('/posts') def posts(): cached_posts = cache.get('all_posts') if not cached_posts: all_posts = Post.query.order_by(Post.timestamp.desc()).all() # 假设Post为对应的model对象 serialized_posts = [post.serialize for post in all_posts] cache.setex('all_posts', timedelta(minutes=5), json.dumps(serialized_posts)) return jsonify(serialized_posts) else: return jsonify(json.loads(cached_posts)) ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值