新零售时代,我们如何提升线下业务的终端可用性?

新零售时代,我们如何提升线下业务的终端可用性?

作者|陈聪(有马)

出品|阿里巴巴新零售淘系技术部


导读:在新零售时代,如何提升线下业务的可用性是一个极其重要的命题,本文从阿里巴巴未来酒店:Flyzoo Hotel 项目出发,介绍了在过程中对这个命题的通用思考,与具体落地的解决方案。


在阿里未来酒店项目中,笔者首次接触了不少线下业务,因为业务的需要,其中大部分是由线下( Android )设备来达成的,如 CheckIn 与 CheckIn 设备,电梯与梯控设备,客房门与门控设备,早餐与早餐核销设备等。


在提高业务可用性的问题上,经历手淘多年的发展,虽然积累了大量可供选择的高可用中间件,但对于酒店这类线下为主的业务,由于线下相比线上,在业务形态与设备环境上有着较大的不同,自然会影响到解题的思路,以及解法的 trade-off,进而会推演出不同的思路与方案。


本文主要介绍对于线下设备可用性方向上的思考,以及基于此而落地的框架与解法,希望能达到一定的抛砖引玉的效果。



01当我们谈论线下可用性的时,在讨论什么


线下业务中,对于那部分以线下设备为核心的业务而言,提高业务可用性的核心是提高设备可用性,更确切而言,是减少设备对用户可感知的,业务功能不可用的时长。

而如何提升的方向,可从线下业务与技术相比线上的不同来着手分析。

1.1 业务上的不同思考


在业务上,线下相比线上主要有如下3个不同点:

1.设备专一业务、业务专一功能

  • 即 CheckIn /门控/梯控等设备只装对应 App,只负责对应业务,只提供对应功能。

  • 一旦 App 功能不可用,就会演变成整个设备不可用

2.用户使用设备的时间是离散和随机的。

  • 事实上,大部分时间是没被使用的,但此时设备还是通电通网的

3.用户容忍度差,遇到问题时需尽快解决和解释

  • 毕竟不像线上业务,购物车挂了还能看商品详情,或者玩别的App

由上述特点,我们认为:

1.提升设备主 App(以及相关核心依赖)的可用性至关重要。

  • 同时, 业务上也需准备周到的降级方案(如机器 checkin -> 人工 checkin ,人脸开门 -> 房卡开门)

2.在用户使用设备提供的业务前,我们有很多时机来检查、感知,甚至解决问题。

  • 如能提前解决,则在用户视角而言是没有发生问题的。

  • 若不能,也可提前告知用户,准备降级,这会比被用户主动发现问题的体验更好

3.为了加快排查与解决问题的速度,要为问题排查准备可及时获取的,充足的问题上下文。

  • 特别的,酒店这种全场景人脸的线下业务,还需要大量图像和深度的上下文


1.2 技术上的不同与思考


技术上,由于线下设备的资源完全可被利用、控制、保障

从而有不少与线上不同的地方,如:

  • 设备永久在线(不在线时,也不存在运维一说,只能去现场了)

  • 设备空间无限(即在用完磁盘前,空间都是这个业务的)

  • 处理能力独占(除系统服务,主要就是自己的 App 了)

  • 无需考虑耗电, 无需考虑设备碎片化, App 可快速更新

  • 系统能力可深度定制,如可在 OS 层提供进程保活的能力,OS 层的数据安全保护等

  • 等等...


所以线上可用性与稳定性的某些方向与优化,可能在线下不是那么重要, 如热更新、启动速度、本地日志大小控制&压缩、减少日志对性能的部分损耗等

而更需考虑的是:

如何在不影响业务 App 运行的情况下,去用(比线上)更多的资源(计算/存储/网络)来交换可用性。


1.3 分解目标 


综上推理,提高线下设备可用性可进一步分解为

通过充分利用设备资源来达成

  • 提前预防问题

  • 快速排查问题


02框架层的解决方案- ShadowKnight


基于上述思路和两个核心子目标,我们设计了 ShadowKnight(以下简称 SK )这款框架,来帮助业务更简单地达成这两个子目标。

下文介绍下该框架的设计思路与方案。

2.1 如何提前预防问题

该目标通过三步完成:

1.建立状态(State)的标准与基础设施

  • 业务可快速与方便地将感兴趣的终端状态暴露给框架 (如当前摄像头是否可用、LED 灯是否可用、门控状态机当前状态、门控当前蓝牙钥匙信息等)。

  • 框架按照调度策略周期性地将设备当前状态同步到云端(diff or 全量),并展示到 Web 上。

  • 业务可基于此快速诊断设备

2.基于统一的 State 标准,构建统一的,业务可配置的云端(钉钉)报警

  • 业务可基于此更快速与便利地得知设备的问题发生

3.建立能力( Skill )的标准与基础设施

  • 业务可快速与方便地将感兴趣的终端能力暴露给框架 (如应用重启,摄像头拍照,应用重装,日志拉取、更新钥匙等)。

  • 框架和云端打通,可通过云端接口或Web交互来执行端侧Skill,并获取结果。

  • 报警触发时,可以自动(基于 State 提前配置)或手动地执行一系列Skill去快速解决问题

此外,为了尽量降低框架复杂度,业务暴露 State/Skill 只需要标注注解或实现接口,而具体的注册或发现由 SK 的 gradle 插件在编译时分析与生成字节码完成。


2.1.1 两种不同的 State 暴露方式


针对不同场景,SK 设计了两类状态暴露方式以满足不同场景需求。

健康检查即状态

业务可通过实现框架的 HealthCheck 接口(有 Major、Minor 两种来满足不同细分场景),来暴露状态。

框架会基于可配置的调度策略,定期调用这些健康检查实例,获取结果,并在合适的时机合并、上报状态。

举个例子:

@HealthChecker("sk.check.minor.camera")
public class CameraHealthChecker implements MinorHealthCheckElement {

   @Override
   public void acceptMinorCheck(@NonNull HealthCheckVisitor healthCheckVisitor) {
       // ...实现具体的检查逻辑,获得结果checkResult
       healthCheckVisitor.submitCheckResult(this, checkResult, null);
   }
   

适合那些需要发起特定调用才能拿到的状态,并且可能有一定成本或者需要一定时间。如门控灯是否可用,蓝牙开锁链路是否通畅,磁盘空间剩余大小,摄像头当前能否获取到深度&RGB数据等。

字段即状态

业务可以直接将类中已存在的字段,将值作为 State 值暴露给框架,框架会自动观测字段的变化,并在合适的时机合并上报状态。

    @StateWatcher
   public class DoorMachine {
   
       // 通过给业务类中已存在的字段的set方法标注注解来暴露
       @KnightState(value = "sk.door.machine.state")
       private void setStateWrapper(@NonNull StateWrapper stateWrapper) {
           this.stateWrapper = stateWrapper;
       }
       
   }

适合业务对自己类中,已有字段感兴趣的场景。比如门控状态机当前状态、设备当前房间号、门控当前钥匙版本等。

同时该暴露 State 的方案成本更低,能降低不少框架复杂度。


2.2 如何快速排查问题


下面介绍对针对,快速排查问题,这个子目标的思路与解法。

为了设计对应的方案,首先需要分析下问题排查的特点。


2.2.1 问题排查的特点


个人认为问题排查可能有以下3个特点:


1.问题上下文越丰富,排查越容易,但过于丰富时,难度又会上升(如很难从成堆的日志中找到真正有用的那条)


2.不需要排查问题时,丰富的上下文是无用资源,而且还可能要为他们存储买单。

  • 以酒店门控设备为例,300台合计一天产生 120 GB 左右的相关日志 (文本+照片+深度)


3.增加上下文的丰富度会带来开发成本的提升


2.2.2 框架的解决方案


基于此, SK 的解决方案是

1.给业务提供一个几乎大小不限高效日志系统,使之可尽可能地多打日志来提升上下文丰富度。

  • 特别的,针对人脸场景,还提供了富日志功能,即单条的日志入参可同时包含文本、图片、深度等。

  • 此外,日志系统也会自动打通 State ,从而可以回溯问题发生时的状态快照

2.日志系统将日志以结构化的方式存储在边缘设备 DB 上。

  • 当想排查问题时,通过在后端或平台页面上输入基于问题编写的 sql 以及其他参数,基于skill,向终端发起一次日志查询,查询结果会返回到 OSS 上。

第2步解决了3个关键问题

1.实时性问题,因为设备永久在线

2.无用资源问题,因为边缘存储

3.上下文过多时带来的排查效率降低问题,因为依靠sql表达能力,可将查询结果收缩到只和问题有关的内容。

  • 同时问题的排查 sql 可以作为模板进行保存,加速下次排查

最后,为了降低由于要增加上下文,而带来的开发成本(写很多日志代码),SK 提供了基于编译时字节码生成的 AOP 日志的功能来解决

业务可给方法标注注解,运行时,框架会自动将方法上下文转换为结构化的日志落库,case 如下:

    @Analyzable(useJSON = true)
   public void onUnlockFailedAndFinish(FHLockError error) {
       // ...业务逻辑
   }


2.3 整体链路


综上,以酒店为例,SK 的整体链路(橙色部分表示SK提供的部分)如下:


新零售时代,我们如何提升线下业务的终端可用性?


这里值得一提的是,在酒店中,所有终端设备的系统架构都是主App + 守护进程的双进程架构方案,从而让设备的运维与业务分离, 具体而言

  • 主 App 负责业务逻辑,以及向 SK 框架注入以业务为主的 State 与 Skill

  • 守护进程负责运维,进而向SK框架注入以运维/ OS /硬件相关的 State 与 Skill ,同时所有 OS 级别的定制 Api 都在这层使用,进而解耦业务 App 与定制化的 OS


2.4 端侧架构


下图是 SK 的端侧架构设计,⼀共分为 7 个模块。


新零售时代,我们如何提升线下业务的终端可用性?

  • SK-Protocol:包含 SK 所有注解和上述模块的核心接口,并提供基于接口依赖注入和实例获取的能力。
    从而业务二方包只需依赖它就行,而 SK 的内部模块间也可以靠它保持解耦的同时,完成互相调用

  • SK-Plugin:编译时的 gradle 插件工程,基于 ASM 提供了 State 与 Analysis 模块中相关功能的字节码增强功能,以及编译时信息收集,生成名为 K 的 class 字节码,注入Common 包

  • SK-Common:提供了网络等上下行功能的注入与实现,从而可让框架不耦合于酒店环境。以及基于 K-Class 向上提供查询能力

  • SK-State:提供了健康检查,字段检测,状态的 merge 与上报等功能。

  • SK-Analysis:提供问题排查相关能力。最下层是 storage 层,提供 db 管理和富文件存储能力,上层是 logger 层,提供 4 类日志接口

  • SK-Skill:提供了 Skill 管理、执行、调用、结果回传等功能

  • SK-Starter:提供 App 编译时只需依赖他就能依赖全家桶,以及开发时一行代码初始化SK所有模块的功能,来降低接入成本


2.5 框架之上


以 SK 框架为基础,在上层我们还构建了几个重要的功能与平台,如训练数据回流、业务开放、人脸排查等,在酒店中发挥了重要的功能。


2.5.1 人脸排查平台 


首先和测试团队合作,基于 SK-Skill & Analysis 打造了人脸排查平台,实现了基本可以在1min 内排查所有场景人脸的问题。

核心功能是可以在可视化页面上基于限定条件精准拉取与显示问题发生时的人脸相关可视化上下文,并带有业务语义与信息。


2.5.2 人脸数据回流


然后和 iDST 以及测试团队合作,基于 SK-Skill & Analysis 打造了人脸数据回流功能,可以每日自动拉取门控上所有训练角度来说有效的照片以及深度,同时还带上了详细的识别信息,作为训练数据。


2.5.3 业务功能开放


基于 SK-Skill ,对合作方暴露各类设备或业务能力,如电梯调度,门控分数调整,设备发现与测试等。


2.6 酒店实践


在酒店中,所有的线下 Android 终端设备均接入了 SK 框架,主要在入场和线上两个阶段产生了一定的作用


2.6.1 入场阶段


入场阶段,核心作用是保障了所有( Android )设备硬件与软件的可用性,帮助与加速业务的进场与上线。

这个阶段,由于酒店定制硬件较多,且定制与改造较大,导致设备的软硬件不够成熟,期间产生种类繁多的全量或随机的问题,如蓝牙天线、门控灯带、摄像头软硬件、连接线、内存泄露、rom 日志、rom 崩溃等等。

我们主要基于 SK 的 State 能力,快速与自动化地发现与定位了大量上述问题,并辅助解决,同时基于 SK 的 Skill 能力去快速实现运维相关需求。

2.6.2 线上阶段

线上阶段,主要作用是两点

1.分钟级别排查业务&设备相关问题

  • 特别的,通过利用人脸排查平台,以及排查模板( sql )的积累让酒店无技术背景的工作人员能独立排查大部分问题,进而解放技术同学的时间与精力

2.对于未解决问题的提前发现&预防&自动解决

  • 上线后,还有不少合作厂商还未完全解决的问题,会小概率发生在酒店设备中,在该类问题在彻底解决前,部分通过 SK 的来自动发现与自动解决/规避,部分通过自动发现后降级人工解决


03结尾


新零售时代,越来越多的公司与团队会更加重视与发力各类线下业务,而提升线下终端可用性必然是业务对技术非常重要与基础的要求,希望本文在这个问题上可以给读到此处的你带来一点帮助或启发。



新零售时代,我们如何提升线下业务的终端可用性?


推荐阅读


新零售时代,我们如何提升线下业务的终端可用性?

历时1年,上百万行代码!首次揭秘手淘全链路性能优化(上)

新零售时代,我们如何提升线下业务的终端可用性?



新零售时代,我们如何提升线下业务的终端可用性?

新零售时代,我们如何提升线下业务的终端可用性?在看点这里


上一篇:Educational Codeforces Round 88 (Rated for Div. 2)【ABCDE】(题解)


下一篇:第八章 网络编程