公众号:编程沉思录
微信云支付Android 智能POS使用WebSocket实现了用户订单的实时推送。即,顾客在扫描了门店的付款码,客户端会随即进行语音播报和打印等动作。
客户端利用WebSocket与后端维持长连接,当后端收到该门店订单时,即将成功态的订单通过对应的连接中。
然而,商户网络环境的多样性会导致WebSocket链路出现各种异常,从而引发漏单问题。
我们根据实际的场景,对此订单推送系统在稳定性上进行了大量优化,尽可能地提升了服务的可用性及自我恢复的能力。
在网络应用的开发过程中,网络的稳定性始终是不可靠的。这点在网络环境多样的客户侧来说,特点尤为明显。
对于以上几种场景,都会引起WebSocket连接异常,导致连接关闭,从而会引发漏单现象。
一旦订单没有得到及时推送,店员虽然可以到交易查询中确认订单状态,但这样的异常行为如果频发,对于客户来说也是很难接受的。
我们引入了以下多种措施来解决此问题
在浏览器端WebSocket相关接口非常简单,但缺了一个设置心跳的接口。我们需要设计一个应用层的心跳机制,来保证线路质量。
在设计应用层心跳时,主要出于以下几个方面:
在最初的版本设计中,我们的应用层心跳只涉及了ping接口。
即客户端主动发生向server端发生ping,如果发送成功,则说明链路正常,反之意味着链路不正常。
整个过程中,ping是否成功,都依赖于WebSocket是否触发了onError错误回调。
但在实际的开发过程中,我们发现,这样一种特殊场景:
使用手机发热点供收银设备使用网络,在正常使用过程中,如果关闭手机的网络数据连接(wifi或者移动数据),但保持热点的正常开放,那么收银设备将无法快速感知到网络的异常,大概需要3-5分钟才能触发异常回调。
因此,针对此情况我们对应用层心跳进行了进一步的优化,让server端收到ping之后,回复一个pong包。我们根据ping和pong的时间间隔,来决定当前链路的健康程度。
当WebSocket连接一旦发生了中断,将不会自动的恢复。因此,WebSocket的断线重连机制也是我们首要考虑的一个方面。
断线重连的实现过程比较简单,即当发生心跳超时、链路错误或者链路非正常关闭等问题时,我们将触发WebSocket的重连机制。
重连过程也非常简单,即不断重新连接WebSocket、重新鉴权等过程,直至连接成功。
这里需要注意的一个小小的点就是:在重新连接的时候, WebSocket的各种回调(onmessage、onopen),都需要重新设置。
有了断线重连机制,可以实现WebSocket简单的自我恢复功能。
引入了WebSocket的应用层心跳检测和断线重连,可以快速地帮我们发现链路的异常问题,同时尽快恢复到健康状态。
但是,当WebSocket服务侧发生了短时异常(如变更等),或者重连时间过长。
在应用层发现异常到重连成功的这个过程,整个推送服务最长可能有十秒左右的不可用时间,这个时长取决于心跳的间隔时长。且万一重连也不成功,这个不可用时间将会持续增大。
在设计中,需要考虑到这种异常情况,且在商户网络环境不稳定的情况下,此问题可能会被放大。
我们引入了主动拉取的方案,在网络异常时,将会切换为主动拉取模式,定时向后端拉取订单。
这里需要注意的有几点:
因为我们主动拉取的范围重叠性以及主动拉取也可能和推送模式有一段时间的重叠,我们得到的订单可能会重复。
这里我们需要注意对订单进行一个简单的去重逻辑,即:
引入主动拉取模式,一方面尽可能的减少了漏单可能的发生,另一方面对主动推送来说,也是一个兜底行为。
总结来说,我们选择使用了WebSocket长连接的方式,实现了支付订单的实时推送,为了解决推送的不稳定性,我们主要采取了以下几种措施:
我们利用这几点措施,使得整个服务的可用性大大增强。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。