写点什么

有赞零售 App 离线切换技术方案

  • 2019-08-18
  • 本文字数:3777 字

    阅读完需:约 12 分钟

有赞零售 App 离线切换技术方案

一、离线模式的价值

有赞零售客户端的用户是需要经营线下门店的商家,在商家的经营时间内,如果软件不能保证正常使用会导致经营效率下降,甚至客户流失。因此除了不断优化软件性能,降低崩溃率,还要做好异常情况的降级处理,比如遇到网络故障和服务器故障等情况时,软件要保证核心功能的可用性,此时软件的工作模式被称为离线模式。


在离线模式下,客户端不能和服务端进行正常的数据通信,所有的数据存储和计算逻辑都要客户端独立完成。目前有赞零售客户端在离线模式下支持登录、收银支付、订单管理、会员积分、部分营销活动等核心功能,即使在极端情况下,有赞零售客户端依然保证商户的经营活动正常进行。


在客户端离线解决方案中主要有两个问题:


1、如何准确及时的触发或退出离线模式。


2、离线场景下的各个业务如何进行数据处理和同步。


本文针对第一个问题,以 iOS 零售客户端为例对其技术实现细节展开分析。

二、离线切换的技术实现

首先我们要清楚商家在什么场景下需要切换到离线模式。试想一下这样的场景:


小明是一名门店收银员,此时正是店里的客流高峰期,收银机前等待结账的顾客已经排起了队,不凑巧的是,此时店里的网络信号很不稳定,开单会等待很久才能有结果,有时会提示网络超时,收银效率很低,排队等待的顾客开始有些不耐烦了,小明只能一边安抚顾客,一边尝试着进行开单收银操作。后来网络彻底断掉,软件无法进行开单操作了,排队的顾客放下准备买的东西离开了,小明只能干等着技术人员来修复网络。


如果以上场景,收银软件能够切换成离线模式,脱离对网络的依赖,确保现有的顾客都能顺利进行结账,收银效率和顾客体验都不会受到影响。此外也存在服务器出现故障的情况,导致客户端的数据请求失败,此时也需要切换到离线模式。因此有赞零售客户端设计了两种切换离线的功能:手动切换能力和针对断网和服务故障的自动切换能力。


为此我们设计一个离线模块用来实现离线模式的触发和退出,它位于业务层和网络层的中间。业务层中各业务模块通过依赖注入的方式获取离线的状态变化和原因,而离线场景下的具体功能由各业务模块实现。业务层通过网络层发送业务数据请求,如果返回的数据出现异常,网络模块会将错误分别发送给业务层和离线模块,离线模块分析接口信息和返回的数据,进而启动服务故障识别功能。



离线模块主要提供三个能力:


  • 离线状态管理

  • 网络故障检测

  • 核心服务故障检测

2.1 离线状态管理

是否处于离线状态是由三个因子共同决定的:


  • 标记离线

  • 网络故障

  • 服务故障


其中标记离线是用户想要主动启动离线模式时,点击指定按钮触发离线模式。网络故障和服务故障是触发离线状态的另外两个条件。我们通过有限状态机维护离线状态的变化,只有当标记离线、网络故障和服务故障的状态都是 False,才会恢复在线状态,否则一直是离线状态。


标记离线通过本地文件缓存来保存状态,因此软件崩溃并不会影响离线状态的管理。对于网络故障,细分为蜂窝移动网络故障还是 WIFI 故障。服务故障解析是根据报错的接口判断出是哪个业务域出的问题。网络故障和服务故障都是实时监测获取状态,具体的监测手段会在下文展开介绍。

2.2 网络故障检测


要实现网络状态的实时监测,我们首先考虑采用苹果官方提供的 Reachability 库,Reachability 的实现依赖于系统提供的 SCNetworkReachability 类,SCNetworkReachability 允许应用程序获取当前系统的网络配置情况,包括网络类型和当前的连接状态。


Reachability 的使用分为同步模式和异步模式。在同步模式下,应用程序主动调用 Reachability 的currentReachabilityStatus方法获取当前的网络连接状态。


currentReachabilityStatus{    NSAssert(_reachabilityRef != NULL, @"currentNetworkStatus called with NULL SCNetworkReachabilityRef");    NetworkStatus returnValue = NotReachable;    SCNetworkReachabilityFlags flags;    // 同步模式获取网络连接状态    if (SCNetworkReachabilityGetFlags(_reachabilityRef, &flags))    {        returnValue = [self networkStatusForFlags: flags];    }
return returnValue;}
复制代码


在异步模式下,应用程序需要调用 Reachability 的startNotifier方法开启一个 RunLoop 去监听网络状态的变化,当网络状态发生变化时,Reachability 会执行ReachabilityCallback回调函数,在这个回调函数里会发送kReachabilityChangedNotification通知,应用程序监听这个通知就可以感知网络状态的变化。源码如下:


- (BOOL)startNotifier{    BOOL returnValue = NO;    SCNetworkReachabilityContext context = {0, (__bridge void *)(self), NULL, NULL, NULL};    // 构造一个监听网络连接状态的上下文信息,详细说明见下面
// 通过调用 SCNetworkReachabilitySetCallback 函数(并传入 Reachability 对象的 ref,以及根据 SCNetworkReachabilityCallBack 自定义的一个回调函数和上述 context)设置 ref 的网络连接状态变化时对应的回调函数为 ReachabilityCallback if (SCNetworkReachabilitySetCallback(_reachabilityRef, ReachabilityCallback, &context)) { // 通过调用 SCNetworkReachabilityScheduleWithRunLoop 函数设置 Reachability 对象的 ref 在 Current Runloop 中对应的模式(kCFRunLoopDefaultMode)开始监听网络状态 if (SCNetworkReachabilityScheduleWithRunLoop(_reachabilityRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode)) { returnValue = YES; } }
// 如果监听成功,返回 YES,否则返回 NO return returnValue;}
...static void ReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void* info){#pragma unused (target, flags) NSCAssert(info != NULL, @"info was NULL in ReachabilityCallback"); NSCAssert([(__bridge NSObject*) info isKindOfClass: [Reachability class]], @"info was wrong class in ReachabilityCallback");
Reachability* noteObject = (__bridge Reachability *)info; // 因为上述 context 传入的是 self(Reachability 对象),所以这里的 info 为 Reachability 对象类型
// 发送一个全局通知告诉监听者网络连接状态已发生改变,可通过 noteObject 获取状态 [[NSNotificationCenter defaultCenter] postNotificationName: kReachabilityChangedNotification object: noteObject];}
复制代码


然而 Reachability 存在一个缺陷,当应用程序可以将一个数据包发出时,SCNetworkReachability 就认为网络是可达的,但是这个数据包是否到达目标地址,SCNetworkReachability 并不清楚,所以它并不能真正检测服务可达性。


于是我们采用一个三方开源库 RealReachability 的方案,这个库是在 Reachability 的基础上进行改进,借助系统的 Socket 库实现的 ping 功能,通过不断对目标地址发送 ping 请求,根据返回的结果判断目标地址是否可达,因而可以更准确的识别当前的网络状态。


在实际应用中,会遇到网络状况时好时坏的情况,RealReachability 的方案会造成业务层频繁地在离线模式和正常模式间来回切换,影响用户体验,有的场景下甚至会导致反复刷新页面,进而引起卡顿。为了解决这个问题,我们在 RealReachability 上再一次进行优化,加入网络防抖功能,它的机制是网络状态的变化不会实时影响离线状态,而是设置一个时间缓冲值 T1,当网络断开时,我们会等待 T1 时间再检查网络是否断开,如果此时网络已经恢复,不会触发离线模式,如果此时网络仍然是断开的,就触发离线模式。在这个缓冲时间内的网络反复变化不会影响离线状态,因此就不会造成频繁的离线切换。



此外 RealReachabilityping 检测的时间间隔为 T2,当发现网络连接断开时,为了及时地检测到网络的恢复,我们会以更快的频率进行 ping 操作,网络恢复后检测的时间间隔也会恢复到 T2。

2.3 服务故障检测

服务故障的检测流程如下图所示:



第一阶段是网络层错误分发,业务层通过网络层发送请求给相应的服务端,当返回的数据出现异常,网络层会启动错误处理的流程,一方面会把错误信息返回给业务层,另一方面把错误信息和请求接口信息一起发给离线模块。


第二阶段是错误信息的本地解析,离线模块维护一份核心业务白名单,这里会配置客户端使用的各个核心业务的接口信息,根据这个白名单可以判断请求的接口所属的业务领域,如果当前报错的接口命中了白名单,离线模块会认为核心业务存在故障风险。


第三阶段是服务端的故障检测,离线模块会请求 QoS 智能决策系统,它根据不同业务后端系统的报警信息来判断是否发生服务故障。如果它判断发生了服务故障,离线模块会收到通知,进而更新本地的离线状态。


第四阶段是故障恢复的检测,离线模块会启动后台线程定期去轮询 QoS 智能决策系统,直到它判断服务故障已经恢复,停止轮询并更新离线状态。

三、展望

本文介绍了零售客户端离线切换解决方案,接下来的问题是业务层如何进行数据处理和同步,以收银开单流程为例,涉及到账号、商品、营销、会员、支付、订单等多个业务模块,各个模块在离线状态下如何存储和处理数据,保证用户在离线状态下可以完成收银功能,以上这些问题我们会在后续文章里详细介绍,敬请期待。



本文转载自公众号有赞 coder(ID:youzan_coder)


原文链接


https://mp.weixin.qq.com/s/ZuQ85PnhOW94m0U4_Yk_2w


2019-08-18 08:003839

评论 1 条评论

发布
用户头像
看文章好像只写了判断离线,但是离线之后如何继续收银还没写完吧
2019-08-19 20:44
回复
没有更多了
发现更多内容

数字样机:飞行器状态控制系统仿真

DevOps和数字孪生

数字样机

文献解读-临床试验-第二十二期|《新抗原负荷作为中国非小细胞肺癌II/III患者的预后和预测标志物》

INSVAST

基因测序 基因数据分析 临床试验

得物App弱网诊断探索之路

得物技术

ios android 企业号2024年7月PK榜

崖山异构数据库迁移利器YMP初体验-Oracle迁移YashanDB

YashanDB

yashandb 崖山数据库 崖山DB

win11基础 开启telnet功能

万里无云万里天

win11 Telnet

win11基础 telnet 检查rabbitmq server是否开启了1883端口

万里无云万里天

RabbitMQ win11 Telnet

即时战略游戏:帝国时代2 for Mac 3.3.1769 中文移植版

你的猪会飞吗

mac软件下载 mac单机游戏

ETL数据集成丨将PostgreSQL数据库数据实时同步至PostgreSQL

RestCloud

postgresql 数据同步 ETL 数据集成平台 数据库同步

LED租赁屏市场

Dylan

LED LED display LED显示屏 市场 舞台表演

极限科技闪耀 2024 可信数据库发展大会,多款自研产品引领搜索技术新纪元

极限实验室

信通院 极限科技 数据库发展大会

开发者必备:淘宝商品列表接口集成全攻略

tbapi

淘宝API接口 淘宝商品列表数据接口 淘宝商品列表数据采集

从0到1:理发店预约剪发小程序开发笔记(上)

CC同学

深度解读GaussDB(for MySQL)与MySQL的COUNT查询并行优化策略

华为云开发者联盟

MySQL 数据库 华为云开发者联盟 企业号2024年7月PK榜

获取闲鱼商品详情api

api开发

技术路线速通!用飞桨让京剧人物照片动起来

百度Geek说

百度飞桨 企业号2024年7月PK榜

数据恢复easyrecovery是磁盘工具吗 easyrecovery数据恢复软件怎么用

阿拉灯神丁

磁盘 EasyRecovery 数据恢复软件 硬盘数据恢复 软件包

AI 应用实战营 - 作业 八 - Coze制作Bot

德拉古蒂洛维奇

参加可观测性Observability Foundation认证培训,您有哪些收益?

雅菲奥朗

可观测性 可观测性认证

AI 应用实战营 - 作业 八 - Coze 制作 Bot - 2

德拉古蒂洛维奇

解读阿里云搜索开发工作台如何快速搭建AI语义搜索及RAG链路

阿里云大数据AI技术

人工智能 自然语言处理 大模型 rag

华为云Serverless可观测性解决方案打造高效、可靠的云原生应用

华为云开发者联盟

云原生 可观测 华为云开发者联盟 企业号2024年7月PK榜

极盾故事|某农商行数据安全制度和数据分类分级建设

极盾科技

数据安全 数据分类分级

最新资讯!2024可信云大会重磅发布《可观测性能力建设指南》!

乘云数字DataBuff

白皮书 可观测平台 可信云大会

win11基础 组件服务 启动分布式com

万里无云万里天

win11 dcom

报名SRE培训,选择哪家培训机构?

雅菲奥朗

SRE SRE培训 SRE认证

PHP 与淘宝详情 API 的融合:构建智能电商应用

api开发

有赞零售 App 离线切换技术方案_技术管理_余颖_InfoQ精选文章