WebSocket系列之socket.io

时间:2022-04-21
本文章向大家介绍WebSocket系列之socket.io,主要内容包括socket.io:、socket.io server:、socket.io client:、断线重连:、多进程和分布式部署:、sticky session(实现代码如下图):、基本概念、基础应用、原理机制和需要注意的事项等,并结合实例形式分析了其使用技巧,希望通过本文能帮助到大家理解应用这部分内容。

导语:上篇讲了WebSocket基础知识和浏览器端的实现,WebSocket server和http server也是有区别的,这篇开始讲nodejs平台的一个很成熟,知名度也最大的WebSocket实现--socket.io

socket.io:

1.跨浏览器、跨平台,多种连接方式自动切换

2.功能完善,心跳检测,断线自动重连

3.server和client必须配套使用,不能直接用原生WebSocket

socket.io server:

socket.io client:

参数说明:

1.client必须引用socket.io的client js文件,没法用原生WebSocket

2.server端的path和client端的path必须对应上,并且server端设置的path也是client引用的js的path

3.server端的serveClient控制socket.io client js是否可以被引用,默认true,如果设为false,那么client里会加载不到socket.io client js文件

4.client端的transports设置的是websocket连接的建立方式,默认值是'polling', 'websocket',可以设置成'websocket',区别是使用默认的会先用http拉取session id,再升级到WebSocket,如果设置成'websocket'会跳过http请求,直接用WebSocket建立连接,如下图:

'polling', 'websocket':

'websocket':

断线重连:

socket.io已经帮我们实现了断线重连,当server close的时候,client会马上探测到并开始尝试重连,如下图

多进程和分布式部署:

看了上面的说明,是不是觉得socket.io真简单,分分钟掌握,开始撸代码,却不知等到你的产品用户量上来的那一天,并发上不去了,你开始得心应手的用cluster开启多进程,还不够,再分部署部署,实现代码如下:

特别说明:你在windows版nodejs测试上面代码时,你会发现每次请求都到同一个worker,看着socket.io多进程正常运行,不过布到linux里就会出现请求400,那是因为windows版nodejs的负载均衡算法和linux不一样(负载均衡算法),linux用的Round-Robin(轮询调度),window版因为Round-Robin有性能问题,暂时用的操作系统的算法,不过文档说等到性能问题解决了,会切到Round-Robin,我们也可以如上面代码第三行,通过设置cluster.schedulingPolicy = 2;为windows开启Round-Robin,一旦开启,就会出现请求400,如下图:

出现400原因是:拉取session id的进程和用该session id建立连接的进程不是同一个,甚至不是同一台服务器,进程A给你分配的session id,进程B当然不认识,也就不会给你建立socket连接了,我们需要保证一个用户的多次连接由同一个进程处理,不仅是session id,也是因为不支持WebSocket的浏览器,socket.io会降级使用轮询实现socket,而这种socket是由多次请求组成的,如果两次请求不是同一个进程处理,运行时都不一致,会出现各种问题

解决方案:上面已经说了,就是保证一个用户的多次连接由同一个进程处理,具体怎么做了,就是nginx代理,原理是nginx支持根据client ip分发请求到对应进程

nginx可以把请求直接分发到nodejs的worker进程,这种就需要同一台机器的各worker进程监听私有端口,并且在nginx配置那里配置对应port,或者由master进程监听一个端口,nginx分发请求到master,再由master分配到worker,这就是socket.io里的sticky session,下面说明

sticky session(实现代码如下图):

说明:

1.根据cpu数开启多进程

2.master监听一个port,启动net server,参数pauseOnConnect:true必须有,因为master接收connect,是为了再分发到worker,master不需要读取数据,数据读取应该由worker来完成

3.根据remoteAddress决定分发给哪个worker,这样就能保证同一个remoteAddress必然由同一个worker处理

至此sticky session实现完成,完美根据client ip分发请求,再也不会请求400了

demo代码都放在附件了,各位可以本地运行试下,当然本地需要安装nodejs和socket.io了

附件: