即时通讯整体解决方案
即时通讯简称IM(Instant Messaging)
需求:用户不只是在消息通知页面可以看到消息,而是在所有页面都能马上得到关注的消息
思考:http只有请求才有响应,但是上面的需求需要服务器主动把关注的消息推送给你,http无法满足
IM的类型:在线推送和离线推送(区别在于应用是否打开)
IM如何构建:我们可以自己搭建WebSocket来推送,或者使用第三方IM服务商提供的服务
IM服务商:
+ 网易云信
+ 融云
+ 环信
+ LeanCloud
即使通讯运用的场景:美团外卖又有新订单了
思考:Http究竟能不能完成即时通讯呢?
图解:HTTP1.0 在每次请求完服务器后,都会断开tcp连接。默认的keepalive是不开启的,无法保持连接
HTTP1.1默认keepalive是开启的
需求:客户端如何通过Http获得服务器数据呢?
轮询:5s发送一次请求,看看有木有新数据(服务器压力比较大)
comet长连接:客户端发起请求,如果服务器没有新数据则不响应,
等到有服务器有新数据响应返回后,客户端立即发起新的请求
缺点:客户端主动请求,不是服务器推送的
新的解决方案(服务器主动推送):
+ WebSocket(由 HTML5定义)
+ HTTP/2
WebSocket
WebSocket定义:是建立在单次TCP连接的全双工通信协议
细节:HTTP是一锤子买卖,WebSocket是建立起长连接,可以互相发送消息
通过上面两图的对比可以知道,WebSocket建立的TCP连接可以发送多次非HTTP协议的数据,这样就能实现服务器主动推送消息了。进行tcp三次握手之后的第一次发送ws握手数据,也是一次握手,正是因为这次握手,两者才建立了持久的连接,并进行双向数据传输。
典型的websocket握手请求格式:
客户端请求
GET / HTTP/1.1
Upgrade: websocket
Connection: Upgrade
Host: example.com
Origin: http://example.com
Sec-WebSocket-Key: sN9cRrP/n9NdMgdcy2VJFQ==
Sec-WebSocket-Version: 13
服务器回应
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: fFBooB7FAkLlXgRSz0BT3v4hq5s=
Sec-WebSocket-Location: ws://example.com/
- Connection必须设置Upgrade,表示客户端希望连接升级。
- Upgrade字段必须设置Websocket,表示希望升级到Websocket协议。
- Sec-WebSocket-Key是随机的字符串,服务器端会用这些数据来构造出一个SHA-1的信息摘要。把“Sec-WebSocket-Key”加上一个特殊字符串“258EAFA5-E914-47DA-95CA-C5AB0DC85B11”,然后计算SHA-1摘要,之后进行BASE-64编码,将结果做为“Sec-WebSocket-Accept”头的值,返回给客户端。如此操作,可以尽量避免普通HTTP请求被误认为Websocket协议。
- Sec-WebSocket-Version 表示支持的Websocket版本。RFC6455要求使用的版本是13,之前草案的版本均应当弃用。
- Origin字段是可选的,通常用来表示在浏览器中发起此Websocket连接所在的页面,类似于Referer。但是,与Referer不同的是,Origin只包含了协议和主机名称。
- 其他一些定义在HTTP协议中的字段,如Cookie等,也可以在Websocket中使用。
优点:
- **较少的控制开销。**在连接创建后,服务器和客户端之间交换数据时,用于协议控制的数据包头部相对较小。在不包含扩展的情况下,对于服务器到客户端的内容,此头部大小只有2至10字节(和数据包长度有关);对于客户端到服务器的内容,此头部还需要加上额外的4字节的掩码。相对于HTTP请求每次都要携带完整的头部,此项开销显著减少了。
- **更强的实时性。由于协议是全双工的,所以服务器可以随时主动给客户端下发数据。**相对于HTTP请求需要等待客户端发起请求服务端才能响应,延迟明显更少;即使是和Comet等类似的长轮询比较,其也能在短时间内更多次地传递数据。
- **保持连接状态。**与HTTP不同的是,Websocket需要先创建连接,这就使得其成为一种有状态的协议,之后通信时可以省略部分状态信息。而HTTP请求可能需要在每个请求都携带状态信息(如身份认证等)。 更好的二进制支持。Websocket定义了二进制帧,相对HTTP,可以更轻松地处理二进制内容。
- 可以支持扩展。Websocket定义了扩展,用户可以扩展协议、实现部分自定义的子协议。如部分浏览器支持压缩等。
- 更好的压缩效果。相对于HTTP压缩,Websocket在适当的扩展支持下,可以沿用之前内容的上下文,在传递类似的数据时,可以显著地提高压缩率。
- 没有同源限制,客户端可以与任意服务器通信。
- 可以发送文本,也可以发送二进制数据。
Socket.IO
细节:Socket .IO是WebSocket封装之后的工具,我们不使用原生的WebSocket进行开发
细节:古老浏览器不支持WebSocket,那么就降级为轮询的方式,所以我们要实现两种方案(哭泣)
缺点:和原生的WebSocket数据传输稍微不一样,所以客户端和服务器端都要使用Socket.IO
安装:pipinstall python-socketio
创建服务器:
方式1:单独部署(如uWSGI、gunicorn)
import socketio # create a Socket.IO serverssio = socketio.Server()# 打包成WSGI应用,可以使用WSGI服务器托管运行app = socketio.WSGIApp(sio) # Flask Django
创建好app对象后,使用uWSGI、或gunicorn服务器运行此对象。
方式2:集成到flask或者 Django 中
from wsgi import app # a Flask, Django, etc. applicationimport socketio# create a Socket.IO serversio = socketio.Server()app = socketio.WSGIApp(sio, app)
方式3:使用协程的方式运行 (推荐)
import eventleteventlet.monkey_patch()import socketioimport eventlet.wsgisio = socketio.Server(async_mode='eventlet') # 指明在evenlet模式下app = socketio.Middleware(sio)eventlet.wsgi.server(eventlet.listen(('', 8000)), app)
方式一:众所周知,wsgi服务器时的工作模式是用多进程或者多线程模式运行应用的,但是如果是这样,客户端每次建立一个请求创建一个线程,这个线程因为长连接一直存在,不能被销毁,这样如果客户端请求特别多,那么线程也特别多,还不能销毁,这样会导致服务器效率低下的。
方式三:协程是方式一的解决方案。
协程
进程-线程-协程的关系:
- 进程和进程之间是隔离的。每个进程各自拥有自己的内存。
- 线程不同之处在于计数器(表示代码执行的位置)
- 进程是操作系统分配资源的最小的单位,线程是操作系统调度(调度就是看看计数器到那里了,那就从那里开始执行代码)的最小单位
- 比喻:进程就是公司,线程就是在公司下做事的我们(有的负责提需求,有的负责开发,有的负责测试),协程就是我手动上有三件事情(函数)(吃饭-看文章-喝水),我吃一口饭,然后停下来看一下文章,在停下来喝一口水,这样反复操作,完成吃饭-看文章-喝水三件事情,速度太快了宏观上感觉是并行处理的。
- 协程调度是由程序员调度了,而不是操作系统,因为这个粒度太小了管不到
- yield 暂停代码,保存/恢复现场(就是恢复程序运行所需的变量)
- gevent和eventlet库是专门操作协程的库
切换的时机:
+ 在程序中发生阻塞的时候(读磁盘,写文件,网络IO操作,收发HTTP请求)
协程库原理:
封装了阻塞的代码,比如原生的read() 被重新封装为:
def read():进行操作系统调用read()非阻塞的yield 暂停代码·
eventlet.mokey_patch()会替换调全部原生的阻塞代码
处理事件
细节:Socket.IO并不是用请求和响应处理数据,而是将数据当作消息,消息根据类别分为事件,然后处理事件
细节:关注通知属于关注事件,评论文章通知属于评论事件,不同消息通知对应不同的事件处理
事件的类型:
+ connect
+ disconnect
+ own event
事件就是给消息打上的标签而已
@sio.on('connect')
def on_connect(sid, environ):"""与客户端建立好连接后被执行:param sid: string sid是socketio为当前连接客户端生成的识别id:param environ: dict 在连接握手时客户端发送的握手数据(HTTP报文解析之后的字典)"""pass@sio.on('disconnect')
def on_disconnect(sid):"""与客户端断开连接后被执行:param sid: string sid是断开连接的客户端id"""pass# 以字符串的形式表示一个自定义事件,事件的定义由前后端约定
@sio.on('my custom event')
def my_custom_event(sid, data):"""自定义事件消息的处理方法:param sid: string sid是发送此事件消息的客户端id:param data: data是客户端发送的消息数据"""pass
发送事件
群发
sio.emit('my event', {'data': 'foobar'})
给指定用户发送
sio.emit('my event', {'data': 'foobar'}, room=user_sid)
给一组用户发送
SocketIO提供了**房间(room)**来为客户端分组
sio.enter_room(sid, room_name)
将连接的客户端添加到一个room
@sio.on('chat')def begin_chat(sid):sio.enter_room(sid, 'chat_users')
注意:当客户端连接后,socketio会自动将客户端添加到以此客户端sid为名的room中
sio.leave_room(sid, room_name)
将客户端从一个room中移除
@sio.on('exit_chat')def exit_chat(sid):sio.leave_room(sid, 'chat_users')
sio.rooms(sid)
查询sid客户端所在的所有房间
给一组用户发送消息的示例
@sio.on('my message') def message(sid, data):sio.emit('my reply', data, room='chat_users')
也可在群组发消息时跳过指定客户端
@sio.on('my message') def message(sid, data):sio.emit('my reply', data, room='chat_users', skip_sid=sid)
使用
send
发送message
事件消息对于**'message’事件**,可以使用send方法
sio.send({'data': 'foobar'})sio.send({'data': 'foobar'}, room=user_sid)
Python客户端操作
import socketiosio = socketio.Client()@sio.on('connect')def on_connect():pass@sio.on('event')def on_event(data):passsio.connect('http://10.211.55.7:8000')sio.wait()
技巧:将多个模块需要使用的对象提取出来,作为模块导入。
细节:所以绑定的事件要先在sio服务器启动前import导入进去,这样服务器才知道它绑定的方法
插件:firecamp来测试sockio
关注业务:
- 首先在web服务器要将关注数据写入数据库中的表中
- 还要将数据写入消息队列,让IM服务器来推送关注用户给博主
细节:IM服务器会不断轮询消息队列去问有木有要推送的任务
关于博主
【如果文章有错误,或者需要学习资料还是想一起学习大数据或者人工智能的朋友可以加下面微信
在朋友圈不定期直播自己的一些学习心得和面试经历。(请备注CSDN)】
即时通讯整体解决方案相关推荐
- 企业OA即时通讯系统解决方案
企业OA即时通讯系统解决方案 一.部署企业即时通讯系统的意义--企业信息化建设 美国市场咨询公司Radicati Group日前公布了关于面向企业的即时通讯市场的调查结果,结果显示,北美85%的企业在 ...
- 2022-2028年中国即时通讯市场投资分析及前景预测报告
[报告类型]产业研究 [出版时间]即时更新(交付时间约3个工作日) [发布机构]智研瞻产业研究院 [报告格式]PDF版 本报告介绍了即时通讯行业相关概述.中国即时通讯行业运行环境.分析了中国即时通讯行 ...
- OpenIM:如何打造安全可靠的即时通讯服务
即时通讯作为移动应用的常用组件,开发起来却并不简单,除了需要研究通讯协议,保证安全性,还要应对复杂的移动网络情况,以提供高可用性的服务.OpenIM是阿里巴巴推出的,集成于阿里百川项目中的移动端 IM ...
- 今天的我家有12口人的即时通讯
今天的我家有12口人的即时通讯,可是,爸爸边点蜡烛,论证流程和论证方法,和橡皮成了一对形影不离的好兄弟,最后得出观点,得到问题的根据,我们帮妈妈过了这次生日,妈妈轻轻的即时通讯摸了一下我的头说. 烛光 ...
- IM即时通讯:快速集成、私有化部署、安全加密
信息社会的不断发展,人们生活的衣食住行都已离不开移动互联网.IM即时通讯在人们的日常生活中充当着社交沟通工具的作用,包括实时沟通.即时音视频通话.文件传输.移动考勤等功能. IM在生活中占据范围逐渐扩 ...
- 基于开源jabber(XMPP)架设内部即时通讯服务的解决方案
原文地址:基于开源jabber(XMPP)架设内部即时通讯服务的解决方案 作者:高傲的活着 Jabber 是著名的即时通讯服务服务器,它是一个自由开源软件,能让用户自己架即时通讯服务器,可以在Inte ...
- php 三方即时通讯_php即时通讯解决方案-请问PHP能否实现即时通讯?
最简单的说,它可以定期刷新,比如10秒的间隔.新数据,反馈到前台,没有新数据等待下次刷新. 但实际上在应用中需要考虑消息的及时性.服务器压力等.php即时通讯. 可以用comet来设计 节点.js.s ...
- ionic/cordova即时通讯解决方案(上)
ionic/cordova即时通讯解决方案(上) 参考文章: (1)ionic/cordova即时通讯解决方案(上) (2)https://www.cnblogs.com/shludan/p/5588 ...
- IM即时通讯仿微信软件平台源码搭建开发解决方案
互联网时代的发展,人们相互之间的沟通交流越来越依赖于即时通讯软件,如(微信.钉钉.QQ等).虽然这些沟通交流平台给我们带来的许多的方便,但是随着平台的发展,对于企业来讲限制和不可控因素也越来越多,时常 ...
最新文章
- mysql 压力测试脚本
- ACMNO.25 C语言-间隔输出 写一函数,输入一个四位数字,要求输出这四个数字字符,但每两个数字间空格。如输入1990,应输出1 9 9 0。 输入 一个四位数 输出 增加空格输出
- Servlet第一篇【介绍Servlet、HTTP协议、WEB目录结构、编写入门Servlet程序、Servlet生命周期】...
- IT人士,你的知识需要管理。
- AVCDecoderConfiguration语法格式分析
- java map赋值_java 中的map怎么没有办法赋值?
- 【JVM性能调优】使用jstack找出最耗CPU的java线程
- kafka 削峰_从面试角度一文学完 Kafka
- requirejs、vue、vuex、vue-route的结合使用,您认为可行吗?
- super在python3和python2_python2与Python3的区别
- 关于oracle数据库论文,Oracle数据库研究论文 有关Oracle数据库的论文
- 高手的作用在于解决难题
- 电脑运行java游戏_电脑里如何运行java软件或游戏
- 【C++ 程序】 解线性方程组(Cramer法则)
- 时间序列--平稳性介绍及检验方法
- 软件单元测试方法,单元测试的基本测试方法
- Python 制作迷宫游戏(一)——地图
- 仓库实现降本增效的秘密法宝,WMS智能仓储系统
- 我37岁,从互联网大厂跳槽到国企后,发现没有一劳永逸的工作。。。
- 关于微软虚拟机更新后密码问题