博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
SSE(Server-sent events)技术在web端消息推送和实时聊天中的使用
阅读量:6258 次
发布时间:2019-06-22

本文共 3531 字,大约阅读时间需要 11 分钟。

最近在公司闲着没事研究了几天,终于搞定了SSE从理论到实际应用,中间还是有一些坑的。

1.SSE简介

SSE(Server-sent events)翻译过来为:服务器发送事件。是基于http协议,和WebSocket的全双工通道(web端和服务端相互通信)相比,SSE只是单通道(服务端主动推送数据到web端),但正是由于此特性,在不需要客户端频繁发送消息给服务端,客户端却需要实时或频繁显示服务端数据的业务场景中可以使用。如:新邮件提示,在浏览网页时提示有新信息或新博客,监控系统实时显示数据。。。

在web端消息推送功能中,由于传统的http协议需要客户端主动发送请求,服务端才会响应;基本的ajax轮寻技术便是如此,但是此方法需要前端不停的发送ajax请求给后端服务,无论后端是否更新都要执行相应的查询,无疑会大大增加服务器压力,浪费不必要的资源。而SSE解决了这种问题,不需前端主动请求,后端如果有更新便会主动推送消息给web端。

在SSE中,浏览器发送一个请求给服务端,通过响应头中的Content-Typetext/event-stream;等 向客户端证明这是一个长连接,发送的是流数据,这时客户端不会关闭连接,一直等待服务端发送数据。

关于SSE的前端用法请自行百度或参考一下连接:

2.python框架flask中SSE的包flask_sse的使用

坑点:刚开始根据,自信的以为在服务器返回数据时只要是response头部添加这三个字段便实现了SSE功能,但是在flask启动自带服务器后,发现浏览器总是触发error事件,并且从新连接。这样的话和ajax轮询没有任何区别。

后来找到flask框架的flask_sse文档   其中发现:

 do not work with Flask’s built-in development server, because it handles HTTP requests one at a time. The SSE stream is intended to be an infinite stream of events, so it will never complete. If you try to run this code on with the built-in development server, the server will be unable to take any other requests once you connect to this stream. Instead, you must use a web server with asychronous workers.  can work with  to use asychronous workers: see .

  flask内置服务器不适合SSE功能,一次只能处理一个请求。所以只能使用具有异步功能的服务器来完成此项功能。所以本人想在不引入任何包的情况下完成此功能是不可能的了。

在官方给出的flask_sse 文档中,使用 gunicorn(WSGI协议的一个容器,和uWSGI一样的功能) + gevent 作为异步功能的服务器。

ubuntu系统中安装:pip install flask-sse gunicorn gevent

由于官方文档中给出的实例代码是MTV(model-template-view)模式,前后端代码杂糅在一起,看着不舒服,于是改成了restful风格的代码。

下面给出restful风格的flask_sse实现的实时聊天(消息推送)功能。

 

后端主要文件

sse.py

1 #coding:utf8 2 # 将程序转换成可以使用gevent框架的异步程序 3 from gevent import monkey 4 monkey.patch_all() 5  6 from flask import Flask, send_from_directory, redirect, url_for, request, jsonify 7 from flask_sse import sse 8  9 app = Flask(__name__)10 #redis路径11 app.config["REDIS_URL"] = "redis://localhost"12 #app注册sse的蓝图,并且访问路由是/stream113 app.register_blueprint(sse, url_prefix='/stream1')14 15 #重定向到发送消息页面16 @app.route('/')17 def index():18     return redirect(url_for('.index', _external=True) + 'upload/'+'send_messages.html')19 20 #接收send_messages.html文件中接口发送的数据,并且通过sse实时推送给用户21 @app.route('/messages',methods=['POST'])22 def send_messages():23     channel=request.values.get('channel')24     message=request.values.get('message')25 26     #关于channel的使用==> http://flask-sse.readthedocs.io/en/latest/advanced.html27     #如channel是channel_bob,则只有channel_bob.html才能接收数据28     #sse推送消息29     sse.publish({
"message": message}, type='social', channel=channel)30 return jsonify({
'code': 200, 'errmsg': 'success', 'data': None})31 32 @app.route('/upload/
')33 def send_file(path):34 return send_from_directory('upload/', path)35 36 if __name__=='__main__':37 app.run()

 

前端接收消息文件

channel_bob.html

1  2  3  4     Flask-SSE Quickstart 5  6  7 

Channel:channel_bob

8
9 10 23 24

 

前端发送消息文件

send_messages.html

1  2  3  4     
5 6 7 8 channel: 9
You can choise these channels: channel_bob,channel_tom,channel_public
10
11 message:12
13 14
15 16 45 46

 

项目上传到github上,有详细注释。

 

坑点:

1.uWSGI配置时,在sse_chait.ini配置文件中,socket参数是给在搭建nginx+uWSGI服务时用的,http参数是uWSGI服务(浏览器直接访问网址)时用的

2.在服务启动时,如果使用uWSGI+gevent启动服务时,要在sse.py顶部添加

from gevent import monkeymonkey.patch_all()

和sse_chait.ini添加

gevent = 100

3.真正的SSE长连接,是一个连接持续工作,并非http请求一样,收到回复就断开连接,如果每次收到响应后,便触发error事件,说明开发的SSE功能有问题。

真正的SSE连接应该如下,响应时间和请求头,响应头如下

 

参考网址:

 

我的博客即将搬运同步至腾讯云+社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan

转载于:https://www.cnblogs.com/rgcLOVEyaya/p/RGC_LOVE_YAYA_624days.html

你可能感兴趣的文章
计算机网络与Internet应用
查看>>
Mars说光场(3)— 光场采集
查看>>
Django 文件下载功能
查看>>
走红日本 阿里云如何能够赢得海外荣耀
查看>>
qt 学习之路2
查看>>
线上应用故障排查之二:高内存占用
查看>>
第四次作业
查看>>
异常处理汇总 ~ 修正果带着你的Code飞奔吧!
查看>>
BFS --- 素数环
查看>>
PCIE_DMA:xapp1052学习笔记
查看>>
python ----字符串基础练习题30道
查看>>
uva-10879-因数分解
查看>>
python 调用aiohttp
查看>>
Spring Boot中使用MyBatis注解配置详解
查看>>
linux下文件的一些文件颜色的含义
查看>>
跨域iframe高度自适应(兼容IE/FF/OP/Chrome)
查看>>
如何花更少的时间学习更多的知识
查看>>
学习鸟哥的Linux私房菜笔记(8)——文件查找与文件管理2
查看>>
升级fedora 18到fedora 19
查看>>
【代码小记】无
查看>>