【详解】WebSocket相关知识整理
前言
记得大概半年前就产生了疑惑,即后台如何主动向前端推送数据。问了下专业老师,知道了原来有一个叫WebSocket的技术可以用于推送数据。于是,当时我就找了个教程,用的是Spring WebSocket。照着敲了一遍,也就搭起来了,依葫芦画瓢而已。当时有其他东西要学,也没有相关的需求,就没再接触过。前阵子刚好要用这个框架,但是API早忘了,就又搜了一遍,发现网上各种各样的案例都有,API都不一样。以下是我这阶段对各种与WebSocket挂钩的知识点的梳理。
数据推送的应用场景
数据推送的应用场景很多,如发送公告,邮件提示啊等等。那么问题是如何推送,换句话说,前端如何获得最新的数据?
推和拉
假如后台更新了一些数据,如添加了一个公告,想要让所有浏览主页的人都看到。那么我要做的,就是把服务器的数据推送给浏览器。我们知道,双方通信必须建立连接。但是问题就来了,HTTP连接的发起方只能是浏览器,而且请求一旦结束,连接就断了。去哪里找连接呢?所以,单纯依赖HTTP来推数据是行不通的。那既然推不动,我客户端主动去拉不就行了。
拉当然是可以的,一种解决方法就是轮询,即每隔一段时间用Ajax请求一遍。这样确实可以达到目的。但是存在两个问题,一个是开销问题,如果你轮询了一个上午,都没有最新消息,那你这一上午发出的请求都是无效请求,都是相当于在骚扰服务器。你可能也意识到了前一个问题,决定把时间间隔设大,来减少请求数。但是这样就可能影响实时性了,也就是说如果在本次无效请求后,数据刚好更新,那么你必须等待一个时间周期结束后,才能获取到最新值。
--------------------------------2019年1月22日补充---------------------------------------------
频繁发请求,就必须频繁地握手,建立连接。这个过程的开销不可忽视,websocket的话,一般只需要建立一次连接,然后不断开,减少了建立连接的开销。
WebSocket技术
WebSocket就是用来解决前面的连接问题的。使用WebSocket时,连接的发起方同样是浏览器,但是不同的是,除非一方主动触发,否则连接一旦建立就不会断开。另外需要注意的是,建立连接,即握手过程,用的还是HTTP协议,这个过程如果顺利的话,就会将HTTP协议升级到WebSocket协议。
WebSocket协议相对于HTTP有何优点?
除了让后台可以主动推数据外,WebSocket还具有以下优点:
- 连接状态可保持,因为是长连接,就不需要像HTTP那样每次都带Cookie这样。
- 更少的控制信息,单纯的WebSocket不需要HTTP那么多的头信息,轻量级。
- 支持扩展,可以扩展协议,如STOMP
-----------------------------2019年2月10日补充--------------------------------
现在使用的Http协议基本都是1.1版本,1.1版本默认都是长连接。除非主动去关闭它,否则后续的请求都会复用这个socket连接。所以,在建立连接的次数方面,WebSocket不占优势。
后备选项 PLAN B
诶,有没有注意到,我前面说的是"如果顺利",难道HTTP升级到Websocket还会失败吗?答案是会。为什么,因为不是所有浏览器都支持WebSocket协议的。那这问题不就出现了吗,我当初是这么想的,你们下个新的浏览器会死啊?!
后来,我冷静思考了一下,我这样想是不对的。因为如果是一个对外网站,一个游客因为浏览器不支持,而不能得到良好的响应效果,你觉得他还会耐心地装新浏览器,再次访问吗?所以,我们必须有后备选项实现推送功能。其实,所谓的后备选项就是轮询。那这时候我们要做的就是前端的工作了,即判断浏览器是否支持,如果支持就用WebSocket,如果不能就用Ajax轮询。但是这样其实工作量挺大的,特别是浏览器还要跟服务端交互,而不仅仅是接收数据的时候。
好在,有一个包含WebSocket和长轮询的框架,SockJS。使用它的时候,如果浏览器支持就用WebSocket传输,如果不支持就用轮询。判断和切换对我们来说是透明的,我们使用它的方法,跟使用WebSocket的API差不多。Spring WebSocket就支持SockJS,服务端配置也方便,绑定连接点的时候加上.withSockJS()即可。
WebSocket的API
服务端发布一个WebSocket连接点的过程:
1.创建连接点类
2.实现该连接点的各个生命周期的方法,如连接建立成功,来消息,连接断开这些回调函数
3.在连接点类中添加业务逻辑,这主要看你的应用需求了
4.发布连接点,其实就是绑定这个连接点类到一个URL,当客户端尝试连接这个URL后,所有的操作由这个类实例完成
JavaEE WebSocket API
JavaEE有相关的API规范,JSR 356。Tomcat实现了这套规范。
需要的包:如果是Spring Boot项目,你勾选了Web选项。那你就有了内置Tomcat,也就直接能用WebSocket了。注:不需要引入Spring-WebSocket。
API使用方式:这个API的使用方式是,创建一个连接点类,标注上@ServerEndPoint("指定的URL")注解,然后在类内部,使用@OnOpen, @OnMessage,@OnClose等注解标识对应的生命周期回调方法。
Spring WebSocket API
Spring WebSocket 在原生基础上,做了些补充,有自己的使用方法。
需要的包:如果是Spring Boot项目要使用Spring的WebSocket,就要勾选WebSocket选项,它就会引入相关的整合包。
API使用方式:注:这里只讲纯WebSocket的使用,不讲扩展内容。Spring把连接点的处理类叫作Handler,创建Handler的方式可以是实现WebSocketHandler接口,或继承已有类TextWebSocketHandler等,你需要根据需要覆盖已有的回调方法。然后在实现了WebSocketConfigurer接口的配置类中,绑定URL。这里需要使用@EnableWebSocket注解开启WebSocket支持。
与原生API的对比:我觉得同样是使用纯WebSocketAPI,Spring因为用的是实现接口的形式,所以它各个回调方法的参数都更明确。而且一看接口就很清楚有哪些回调方法。而如果使用@OnOpen,@OnMessage等注解,你根本不清楚注解的方法,支持哪些参数,参数到底是什么类型的。这些你看注解代码都看不出来,需要看官方的说明才清楚。
扩展内容:Spring除了让你能使用纯WebSocket外,还支持其他扩展。如支持SockJS使得浏览器.都能接受推送数据,支持WebSocket扩展协议STOMP,使得能够像消息机制那样使用WebSocket。
使用程度:Spring WebSocket支持扩展,你可以自己决定用到什么程度。
1.纯WebSocket,部分浏览器不支持。如果你确定用户使用的浏览器都没问题,用到这层就够了。
2.支持SockJS(WebSocket + 长轮询),服务端改动的话,只需要加withSockJS即可。所有浏览器都支持
3.纯WebSocket/SockJS + STOMP。这种时候是队列使用的是In-Memory的MQ。消息机制,可发布订阅,实现广播。
4.纯WebSocket/SockJS + STOMP + ActiveMQ/RabbitMQ。引入第三方消息队列。这时候消息就能持久化,防止因服务器宕机,导致消息丢失。
注意:使用STOMP,并不一定要配合SockJS。
Socket.IO
Socket.IO是单独的一套WebSocketAPI。它使用的Engine.IO引擎也能够切换传输方式,即所有浏览器都支持,相当于SockJS吧。它的分组机制,使得它也能够广播消息,暂时不知道是否支持STOMP扩展。它官方提供的服务端实现是Node版,客户端支持多种语言。Java如果要使用它的服务端的话,可以使用一个开源的用Netty实现的框架netty-socketio。
目前就Spring-WebSocket与Socket.IO的性能优劣还不甚了解。
【详解】WebSocket相关知识整理的更多相关文章
- Spring AOP四种实现方式Demo详解与相关知识探究
一.前言 在网络上看到一篇博客Spring实现AOP的4种方式,博主写的很通俗易懂,但排版实在抓狂,对于我这么一个对排版.代码格式有强迫症的人来说,实在是不能忍受~~~~(>_<)~~~~ ...
- Linux dts 设备树详解(一) 基础知识
Linux dts 设备树详解(一) 基础知识 Linux dts 设备树详解(二) 动手编写设备树dts 文章目录 1 前言 2 概念 2.1 什么是设备树 dts(device tree)? 2. ...
- slf4j log4j logback关系详解和相关用法
slf4j log4j logback关系详解和相关用法 写java也有一段时间了,一直都有用slf4j log4j输出日志的习惯.但是始终都是抱着"拿来主义"的态度,复制粘贴下配 ...
- slf4j log4j logback log4j2关系详解和相关用法
来源:slf4j log4j logback关系详解和相关用法https://www.cnblogs.com/Sinte-Beuve/p/5758971.html The Simple Logging ...
- Redis相关知识整理
Redis相关知识整理 1. Redis和MySQL的区别?a).mysql是关系型数据库,而redis是NOSQL,非关系型数据库.mysql将数据持久化到硬盘,读取数据慢,而redis数据先存储在 ...
- slf4j、log4j、 logback关系详解和相关用法
slf4j log4j logback关系详解和相关用法 写java也有一段时间了,一直都有用slf4j log4j输出日志的习惯.但是始终都是抱着“拿来主义”的态度,复制粘贴下配置文件就开始编码了, ...
- Web缓存相关知识整理
一.前言 工作上遇到一个这样的需求,一个H5页面在APP端,如果勾选已读状态,则下次打开该链接,会跳过此页面.用到了HTML5 的本地存储 API 中的 localStorage作为解决方案,回顾了 ...
- 一文详解 WebSocket 网络协议
WebSocket 协议运行在TCP协议之上,与Http协议同属于应用层网络数据传输协议.WebSocket相比于Http协议最大的特点是:允许服务端主动向客户端推送数据(从而解决Http 1.1协议 ...
- podSpec文件相关知识整理
上一篇文章整理了我用SVN创建私有库的过程,本文将整理一下有关podSpec文件的相关知识. podSpec中spec的全称是“Specification”,说明书的意思.顾名思义,这是用来描述你这个 ...
随机推荐
- Python6大设计原则
内容总览 六大设计原则都有哪些 一.单一职责原则 二.里氏替换原则 三.依赖倒置原则 四.接口隔离原则 五.迪米特法则 六.开放封闭原则 内容详解 一.单一职责原则 单一职责原则:英文名称是Singl ...
- Debian 使用 Samba 服务为 Windows 客户端和 Linux 客户端提供文件服务
1 目标 1.1 主机采用 Debian,为 Windows 和 Liunx 客户端提供文件存取服务 1.2 Windows 采用 GB2312 编码,Linux 采用 UTF-8 编码,要求中文不出 ...
- 要开始学习C#
之前有涉及ASP.NET,但是就仅涉及workflow这点,现在再接触还是有点陌生. 整理一些VS使用小技巧: 1,for cw ctor 按两下Tab键会出现整个的语句 2,Ctrl+shift ...
- 2019.02.11 bzoj4767: 两双手(组合数学+容斥dp)
传送门 题意简述:你要从(0,0)(0,0)(0,0)走到(ex,ey)(ex,ey)(ex,ey),每次可以从(x,y)(x,y)(x,y)走到(x+ax,y+ay)(x+ax,y+ay)(x+ax ...
- python open()函数的模式选择
python open()函数打开文件的模式详解 使用python处理文件时,避免不了要用到open()函数.我们今天主要讨论mode参数的区分. fd = open('文件名(路径)’, mode= ...
- Python开发——5.函数
一.函数的定义 def test(x) "The Function definitions" x += return x def:定义函数的关键字 test:函数名 ():定义形参 ...
- pyhon_day1 格式化输出
格式化输出 我们在写Python的在很多时候输出的内容需要规定格式的,这样就引入到了格式化输出 定义: 盗用下大咖的例子: ------------ info of alex ----------- ...
- [ 9.26 ]CF每日一题系列—— 771B递推问题
Description: 给定你命名的规律,1-10个字符,开头必须大写,最多有50个名字,然后告诉你有n个人,判断区间长度为k,那么你将得到n - k + 1个答案(YES or NO) 表示1 - ...
- hive 语法 case when 语法
' then '精选' else null end as sale_type 注意: end不能少
- Solutions and Summay for Linked List Naive and Easy Questions
1.Remove Linked List Elements package linkedlist; /* * Question: Remove all elements from a linked l ...