【分布式WebSocket – 1】超详细!WebSocket协议详解

  • Post author:
  • Post category:其他




背景

在项目开发时,我们经常需要与服务器进行持续的通讯以保持双方信息的同步。通常这种持久通讯在不刷新页面的情况下进行,消耗一定的内存资源常驻后台,并且对于用户不可见。就聊天的功能来说,在 WebSocket 出现之前,我们有以下解决方案:


传统轮询(Traditional Polling)

image-20210608204214228

主要通过 Ajax 轮询请求,每隔一秒或者一段时间请求一次服务器查看是否有未读消息。浏览器需要不断的向服务器发送请求,而 HTTP 请求可能包含比较长的头部信息,其中真正有效的数据只占了一小部分,而每次请求数据都要发送一段很长的信息,会浪费很多的带宽等资源。


长轮询(Long Polling)

image-20210608204323917

每一个请求发送到服务器时,服务器将请求卡主,直到有消息时才返回。这种方案会造成服务器很多连接占用。如果tomcat设置的连接数较少,会有无法连接的情况。还要注意默认http请求超时时间。

长轮询简易代码示例:

@GetMapping("/pull")
public string pull(){
	while(true){
		String message = messageService.pull();
		if(message !=null ){
		   return message;
		}
	}
	return null;
}

通过死循环或者notify/wait都可以,总之就是卡住请求不响应,一直等待有消息才响应。



一、什么是WebSocket

WebSocket 协议在2008年诞生,2011年成为国际标准。所有浏览器都已经支持了。WebSocket 是一种全新的协议。它将 TCP 的

Socket(套接字)

应用在了web page上,从而使通信双方建立起一个保持在活动状态连接通道,并且属于全双工(双方同时进行双向通信)。WebSocket 协议是借用 HTTP协议 的

101 switch protocol

来达到协议转换的,从HTTP协议切换成WebSocket通信协议。它的最大特点就是,

服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话



二、WebSocket场景



2.1、社交场景

在线聊天场景,例如qq聊天、淘宝与客服聊天、在线客服等等。这种场景都是需要实时的接收服务器推送的内容。

image-20210608163238057



2.2、协同办公 / 编辑

腾讯在线文档,腾讯的在线文档是支持多人编辑的。在excel中,一旦有人修改就要立即同步给所有人。



2.3、直播弹幕

虎牙、斗鱼等各大直播平台,在直播时都是有弹幕的,遇到一些精彩片段时,往往一堆堆的弹幕刷屏。在这种情况下使用WebSocket会有一个更好的用户体验。



2.4、位置共享

微信里是有位置共享的,这种场景是需要用户实时的共享自己的位置给服务器,服务器收到位置信息后,要实时的推送给其它共享者的。这种是实时性要求较高。

百度地图导航系统,在自己位置到达某个地方之后,语音会立即播报前面道路情况,比如上高架、下地道、拐弯、直行、学校慢行等等。这种场景实时性特别高。汽车速度很快,延迟1秒钟,可能就错过了最佳提醒时机。



三、判断是否使用WebSocket

  1. 服务器是否向客户端推送数据
  2. 服务端向客户端推送数据的频率很大
  3. 实时性要求高

这时我就想到一个比较纠结的场景:

web扫码登录

image-20210608165637100

扫码登录,在手机端认证登录之后。web是循环拉取认证结果,还是服务器推送。这里其实实时性也是有的,因为用户扫码之后,就在等待登录跳转。在登录的压力不大的情况,即使循环拉取,也不会造成很大的影响。如果压力大的情况下,可以采用WebSocket。



四、WebSocket协议解析

image-20210608165637100

为了建立一个WebSocket连接,浏览器需要向服务器发送一个HTTP请求,这个请求和普通的HTTP请求不同。请求头中需要附加

Upgrade: WebSocket

。这样表示这是一个申请协议升级的HTTP请求。

GET /spring-WebSocket-portfolio/portfolio HTTP/1.1
Host: localhost:8080
Upgrade: WebSocket 
Connection: Upgrade 
Sec-WebSocket-Key: Uc9l9TMkWGbHFD2qnFHltg==
Sec-WebSocket-Protocol: v10.stomp, v11.stomp
Sec-WebSocket-Version: 13
Origin: http://localhost:8080

服务器解析对应的请求头进行响应。

HTTP/1.1 101 Switching Protocols 
Upgrade: WebSocket
Connection: Upgrade
Sec-WebSocket-Accept: 1qVdfYHU9hPOl4JYYNXF623Gzn0=
Sec-WebSocket-Protocol: v10.stomp

成功响应的状态码为

101

,同样也有Upgrade表示服务器同意协议升级。成功握手后,HTTP 升级请求底层的 TCP 套接字保持打开状态,客户端和服务器都可以继续发送和接收消息。

请求消息中

Sec-WebSocket-Key

是随机的,服务器会用这些数据构造出一个SHA-1的信息摘要,把

Sec-WebSocket-Key

加上一个魔幻字符串。使用SHA-1加密,然后进行BASE-64编码,结果做为

Sec-WebSocket-Accept

头的值,返回给客户端。

有兴趣的小伙伴可以在

在线WebSocket调试

,通过浏览器开发者工具进行抓包查看。



五、WebSocket与http的区别

img

WebSocket 和 HTTP 的异同点

  • 相同点:

    • 都是基于 TCP 的可靠性传输协议
    • 都工作在应用层
  • 不同点

    • WebSocket 中,浏览器和服务器只需要完成一次握手,就能建立持久性的连接,并进行双向数据传输(WebSocket在建立握手时,数据是通过HTTP传输的。但是建立之后,是不需要HTTP协议的);建立了WebSocket 之后服务器不必在浏览器发送 request 请求之后才能发送信息到浏览器,服务器可以主动向浏览器发送数据,而且信息当中不必再带有 head 的部分信息了。与http的长链接通信相比,这种方式,不仅能降低服务器的压力,而且信息当中也减少了部分多余的信息,节省了带宽。
    • HTTP 是单向的,浏览器与服务器进行通信,必须由浏览器发起请求,然后服务器返回结果(http链接分为短链接,长链接,短链接是每次请求都要三次握手才能发送自己的信息。即每一个request对应一个response。长链接是在一定的期限内保持 TCP 连接不断开。)