写点什么

有赞零售 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:003675

评论 1 条评论

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

按图搜索的精准营销:基于拍立淘API返回值的用户画像

技术冰糖葫芦

API Explorer API 接口 API 测试 API】

大促高并发系统性能优化实战--京东联盟广告推荐系统

京东科技开发者

2024-08-14:用go语言,给定两个长度分别为n和m的整数数组nums和changeIndices,下标从1开始。初始时,nums 中所有下标均未标记。 从第1秒到第m秒,每秒可以选择以下四种操

福大大架构师每日一题

福大大架构师每日一题

JProfiler for Mac(Java开发分析软件) v14.0.0永久激活版

理理

VM虚拟机VMware Fusion Pro 13:打破界限,实现多平台的无缝融合

理理

NCH WavePad for Mac(强大的mac音频编辑软件) v19.55注册版

Mac相关知识分享

视频编辑器

哪里有Photoshop 2024激活补丁?PS2024中文破解资源分享【mac&win】

理理

cad2024安装教程分享 Autodesk AutoCAD 2024 v2024.3中文版 附破解补丁

理理

Author for Mac(文档编辑工具)

Mac相关知识分享

办公软件 文档编辑软件

PDF编辑软件 Acrobat DC 2023中文直装下载 【mac&win】

理理

【mac 软件推荐】SecureCRT for mac(终端SSH工具)永久激活

理理

变“金点子”为“好应用”,合合信息智能文档处理技术助力大学生探索AI创新边界

合合技术团队

人工智能 科技 比赛 合合信息

The Difference Between Router Mode and Bridge Mode

wallyslilly

科大讯飞p30和c10s、c10区别 选哪个好

妙龙

科大讯飞 学习机

淘宝商品评论接口API:获取淘宝商品评论数据评论总数(支持排序)

tbapi

淘宝API接口 淘宝商品评论接口 淘宝商品评论数据 淘宝商品评论API

SVN管理工具Cornerstone for mac永久破解版 及Cornerstone详细使用教程

理理

强大的视频下载工具4K Video Downloader for Mac中文激活版

Mac相关知识分享

视频下载 Mac软件 视频下载工具

Postbox for Mac(邮件客户端)v7.0.62激活版

Mac相关知识分享

邮件管理 Mac软件

人工智能 | 打造领域专属的大语言模型

测试人

软件测试

「重构:改善既有代码的设计」实战篇

京东科技开发者

ForkLift for Mac(文件管理程序)v4.1.6激活版

Mac相关知识分享

Mac软件 文件管理程序

万界星空科技AI低代码MES,引领制造业智能化新潮流

万界星空科技

低代码 低代码平台 mes 万界星空科技 低代码云MES

周期补数据、定时补数据,深入了解两种补数据的特殊方式

袋鼠云数栈

大数据

全球首发!昆仑万维重磅推出AI流媒体音乐平台Melodio

新消费日报

苹果电脑如何安装Windows11系统?借助PD虚拟机,mac电脑也能安装Win11了!

理理

【永久版】Axure RP 9中文授权码 mac&win

理理

ETL数据集成丨将SQL Server数据同步至Oracle的具体实现

RestCloud

数据库 oracle ETL 数据集成 SQL Server

提升团队效率:最佳文件管理软件7选

爱吃小舅的鱼

文件管理 文件管理软件

当系统闹脾气:用「因果推断」哄稳技术的心

京东科技开发者

打造领域专属的大语言模型

霍格沃兹测试开发学社

KubeCon China 2024 | KubeEdge 邀您共话边云协同AI智算

华为云原生团队

云计算 容器 云原生

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