websocket如何保证稳定性

「Offer 驾到,掘友接招!我正在参与2022春招系列活动-经验复盘,点击查看 活动详情

一、项目简介:

综述:

  • 我的项目是一个后台系统能实时显示来自手机上的订单
  • 我实现的目标就是数据能够实时同步

二、项目背景:

数据同步在业务中其实经常会碰到,举一些常用APP的例子:

  1. 比如滴滴出行有乘客端和司机端,司机端的状态需要实时同步给乘客,乘客可以看到司机是否到达上车点。
  2. 比如美团外卖有骑手端和客户端,骑士的接单状态需要实时同步给用户,用户可以知道骑手是否送达。
  3. 点餐系统需要实时获取扫码点餐的用户下单情况,及时处理用户的订单。

这些都要涉及多端之间的数据同步,要怎样保证数据的及时性和准确性是项目的难点,我们还要考虑各种突发情况,比如用户网络不好订单无法及时更新,服务端不稳定数据无法及时更新等等问题。

三、实践过程:

  1. 技术选型:websocket+心跳包+重接+轮询

我的项目场景是后台需要实时显示来自手机端的订单,如果单纯的用websocket也没问题,但是实践过程中遇到的问题是,手机断开网络了,如果websocket不发消息,websocket是不会立即触发error事件的,这样就导致了订单没有及时更新,所以我们就需要加心跳包。

心跳包是什么?就是客户端每隔一段时间向服务器发送一条消息,那么服务端也需要配合我们,发了消息之后需要立马应答我,然后客户端就知道两人都一切正常没毛病,过几秒钟之后再次发消息。这样就确保两端之间正常。

客户端:你在吗?
服务端:在的

客户端:你在吗?
服务端:在的

客户端:你在吗?
服务端:在的
复制代码

如何我问了你“你在吗?”,但是你很久都没回复我,那说明你有问题,这个时候可以关闭websocket重新连接。断线重连是我们的重要环节,一旦发现消息久久没有回复,或者触发的error事件,都要立刻关闭websocket连接进行重连。重连最好加个次数限制,比如重连了10次没有反应就不再连接了。这个时候我们可以改成轮询方式,进行定时拉取服务的数据。

其实服务端的数据单靠websocket通知是不够的,但是实践过程中遇到的问题是服务端推送机制老是阻塞出现异常,服务端不能及时把消息发送给客户端。那遇到这样的问题就需要websocket+轮询同时进行,一个坏了另一个可以继续用,但是如果两个坏了就真的没戏了。

在设计的过程中websocket+轮询配合使用,由于考虑到性能问题,我们可以把轮询的时间间隔变大一点,比如5s轮询接口一次,毕竟加了websocket能把消息发过来。一旦发现websocket不行了出问题了,我们可以把轮询的时间调短一点比如1s更新一次。

由于websocket+轮询的两种方式同时进行,数据的及时性可以提高很多,但是有些人又会问,那干脆直接都用轮询得了搞得这么麻烦,其实轮询由于存在时间间隔,不知道服务端什么时候数据更新,而websocket可以让服务端立马通知给客户端数据更新。

最后再提一句,由于使用了轮询会给服务端带来压力,所以你们的服务器如果抗不住最好就不要加了,可以把websocket稳定性做好就可以。毕竟适合自己的才是最好的。

五、总结思考:

做好实时数据同步的稳定性真的很重要,我的项目一开始也是单纯的只有websocket,会导致后台系统的无法及时的收到来自手机端的订单,又由于订单信息是非常重要的,所以我们需要把性能做好。面对这样的问题,我们可以使用多种法案融合在一起,一个坏了另一个可以继续用。

另外还需要注意一些边界情况,由于websocket+轮询的两种方式比较消耗性能,需要在离开页面的时候把这些东西清除掉,也就是关闭连接关闭轮询。

所以我的最佳实践是:

网络正常的情况:
websocket和心跳包 + 5s的轮询

网络异常的情况:
websocket(进行10次重连) + 1s的轮询

如果10次重连都出问题,那么直接关闭,仅使用1s的轮询

如果10次重连一但连接上,那么继续使用5s的轮询
复制代码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享