近年,不管是正在快速增加的直播,远程教育以及IM聊天场景,仍是在常规企业级系统中用到的系统提醒,对websocket的需求愈来愈大,对websocket的要求也愈来愈高。从早期对websocket的应用仅限于少部分功能和IM等特殊场景,逐步发展为追求支持高并发,百万、千万级每秒通信的高可用websocket服务。前端
面对各类新场景对websocket功能和性能愈来愈高的需求,不一样的团队有不一样的选择,有的直接使用由专业团队开发的成熟稳定的第三方websocket服务,有些则选择自建websocket服务。vue
做为一个具备多年websocket开发经验的老程序猿,经历了GoEasy企业级websocket服务从无到有,从小到大的过程,此文是根据过去几年在GoEasy开发过程当中踩过的坑,以及为众多开发团队提供websocket服务、与众多开发者交流中的总结的一些经验和体会。react
此次主要从搭建websocket服务的基本功能和特性方面作一些分享,下次有机会再从构建一个高可用websocket时要面对的高并发,海量消息,集群容灾,横向扩展,以及自动化运维等方面进更多的分享。web
如下几点是我的认为在构建websocket服务时必需要考虑的一些技术特性以及能显著提升用户体验的功能,供各位同窗参考:编程
1.创建心跳机制
心跳机制几乎是全部网络编程的第一步,常常容易被新手忽略。由于在websocket长链接中,客户端和服务端并不会一直通讯,若是双方长期没有沟通则都不清楚彼此当前状态,因此须要发送一段很小的报文告诉对方“我还活着”。另外还有两个目的:
服务端检测到某个客户端迟迟没有心跳过来能够主动关闭通道,让它下线;
客户端检测到某个服务端迟迟没有响应心跳也能重连获取一个新的链接。小程序
2.创建具备良好兼容性的客户端SDK
虽然说如今主流浏览器都支持websocket,但在编码中仍是会遇到浏览器兼容性问题,并且经过websocket通讯的客户端早已不只限于各类web浏览器,还包括愈来愈多的APP,小程序。所以就要求构建的websocket服务必须可以很友好的支持各类客户端。最好的方式就是构建一个可以兼容全部主流浏览器、小程序和APP,以及uni-app、vue、react-native等目前常见的各类前端框架的客户端SDK,这样不论公司的各个项目使用什么样的前端技术,都可以快速的集成websocket服务。react-native
3.断网自动重连和消息补发机制
移动互联网时代,终端用户所处的网络环境多样且复杂,如用户进出电梯,出入地下室或地铁等网络不稳定的场所,或其余缘由致使的网络不稳定都是很常见的场景。所以,一个可靠的websocket服务必须具有完善的断网自动重连机制。确保断网后,网络一旦恢复,能第一时间自动从新创建长链接,而且可以当即补发在网络不稳按期间发送的消息。浏览器
4.离线消息
基础的Websocket通信从技术上来讲,消息送达的前提条件就是创建起一个长链接,没有创建网络链接就来讨论通信那是耍流氓。可是从使用者的角度上来讲,随手关闭浏览器,或者将小程序、APP进程直接杀掉而致使网络链接断开的状况是随时都在发生的。而后咱们下意识的期待,就是我下次打开浏览器访问网页,或者打开APP时,可以收到用户离开系统期间的全部信息。从技术上这是一个跟websocket没有多大关系的需求,但实际上倒是websocket服务不可或缺的基本特性,也是一个可以极大提高用户体验的功能。缓存
5.上下线提醒,客户端在线列表
掌握当前系统有哪些用户在线,捕捉用户上下线事件,是搭建一个企业级websocket服务,必不可少的特性,尤为是开发IM和游戏类产品。安全
6.支持历史消息查询
websocket服务,某种意义也是属于一个消息系统,对于历史消息的查询需求,是没法绕开的话题。好比IM系统中常见的历史消息,所以在websocket服务内部实现一个高速,可靠的消息队列机制来支持websocket服务实现历史消息的查询就是一个必须的工做。
7.消息的压缩机制
不管是为了保证消息通信的速度和实时性,仍是为了节约流量和带宽费用,或者是出于提升网卡的使用效率和增长系统的吞吐量,在通信过程当中对消息进行必要的压缩都是必不可少的。
除了须要考虑以上七点之外,笔者认为,还有几个问题也是很值得初学者积极关注的:
1.缓存和持久化
选择合适的消息缓存机制,是企业级websocket服务保证性能必需要考虑的问题。
2.异步调用
要支持大量消息通信的高性能系统,必然推荐异步调用。若设计为同步调用,调用方就须要一直等待被调用方完成。若是一层一层的同步调用下去,全部的调用方须要相同的等待时间,调用方的资源会被大量的浪费。更糟糕的是一旦被调用方出问题,其余调用就会出现多米诺骨牌效应跟着出问题,致使故障蔓延。收到请求当即返回结果,而后再异步执行,不只能够增长系统的吞吐量,最大的好处是让服务之间的解耦更为完全。
3.独立于业务和标准化
尽管在一个web项目中能够同时存在常规http服务和websocket服务,尤为对性能要求不高的单应用web系统,这种方式更简单,更便于维护。但对于性能和可用性高的企业级系统或者互联网平台,更好的方式,是将websocket服务做为一个单独的微服务来进行设计,避免和常规的http服务抢占资源,致使系统性能不可控,同时也更便于横向扩展。
一个设计良好的企业级websocket服务应该是一个独立于业务系统、标准化的单独存在的技术性微服务,可以做为公司基础架构的一部分为公司的全部项目提供通信服务。
4.幂等性和重复消息的过滤
所谓幂等性,就是一次和屡次请求一个接口都应该具备一样的后果。为何须要?对每一个接口的调用都会有三种可能的结果:成功,失败和超时。对最后一种的缘由不少多是网络丢包,可能请求没有到达,也有可能返回没有收到。因而在对接口的调用时每每都会有重试机制,但重试机制很容易致使消息的重复发送,从用户层面这每每是不可接受的,所以在接口的设计时,咱们就须要考虑接口的幂等性,确保同一条消息发送一次和十次都不回致使消息的重复到达。
5.支持QoS 服务质量分级
其实对于上一点消息重复的问题,行业已经有了解决方案和标准规范,对于消息到达率和重复,经常使用的手段就是经过消息确认的方式来确保消息到达,要求越高,意味着确认机制越复杂,成本越高。为了在成本和到达率之间有很好的平衡,一般对消息系统的服务质量(QoS)分为如下三个级别 :
QoS 0(At most once):“最多发一次”,意味着发送就能够了,不须要确认机制,发送了便可,适用于要求不高的场景,能够接受必定的不到达率,成本最低。
QoS 1(At least once):“至少发一次”,意味着发送方必须明确收到接收方的确认信号,不然就会反复发,每条消息至少须要两次通讯来确认到达,能够接受一些消息被重发,但成本不高 。
QoS 2(Exactly once):“确保只发一次”,意味着每条消息只能到达一次,且不容许重复到达,为了达到这个目标就须要双方至少通信三次,成本最高。
一个完善的websocket服务面对不一样的应用场景,应该可以支持选择不一样等级的QoS,在成本和服务质量之间取得平衡。
最后
虽然websocket已经普遍的应用于各类系统和平台,但若是要搭建一个知足企业级或者大型互联网平台的可靠、安全稳定的websocket服务,对于没有经验的同窗,在具体的技术实践过程依然是有很多的坑要踩。
对websocket服务有较高要求,选择成熟可靠的第三方websocket服务其实也是一个成本更低和高效的选择。GoEasy做为国内领先的第三方websocket消息平台,已经稳定运行了5年时间,支持千万级消息并发,除了兼容全部常见的浏览器之外,同时也兼容uni-app,各类小程序,以及vue、react-native等常见的前端框架。
但愿本文能为初次搭建websocket服务的同窗在思路上有所帮助和参考,也欢迎各位前辈多多批评指正,同时也但愿将来有机会就更多的技术与你们进行交流。GoEasy官网:www.goeasy.io 微信:GoEasySupport