移动端发展至今,诞生了很多架构用于解决各领域的专有问题。比如针对移动端动态化的Hybrid方案;兼顾动态化和性能的RN、WEEX乃至界面搭建方案;针对热修复的各种Patch方案;还有一些配置、编排等特殊需求的方案。这些方案的核心都是用某种语言描述业务的逻辑方法,描述能力越强大,能够解决的问题越多。脚本语言似乎有着无限的可能性,但是当我们尝试解决某个未知领域的计算问题,对于问题计算的可行性又缺少自信。此外,正确评估各种架构的计算性极限对于我们选型、解决具体问题也是十分重要的。因此需要总结如何设计、评估端计算架构的一般性方法。
一 从解决埋点热修问题理解何为端计算
因众所周知的原因,苹果禁止类似JSPatch的热修复方案上线。对于考拉iOS客户端,大多数问题需要发版解决。通过发版解决数据问题,周期长且持续产生脏数据。对于依赖数据驱动产品迭代的开发方式会产生很大影响。同时,我也在思索是否有一种更敏捷的移动端取数方案,缩短数据试验周期。基于以上目的,埋点热修方案的研发就提上了日程。
虽然我们可以使用JS脚本作为计算载体,但是需要证明埋点热修是否可通过计算修复。
如上图所示,埋点修复其实就是将一个错误的字典计算为一个正确字典的过程。如果满足下面两个条件,则可以修正任何错误的埋点数据:
-
能够无二义性的识别错误数据。
-
完备的数据,可以计算出正确的数据。
要满足第一个条件,可以根据字典本身的数据特征、交互特征、当前页面等上下文数据来识别。埋点数据源自服务端返回数据、前端位置及交互和页面上下文。要满足第二个条件,只需要补充上述数据即可。因此接入的数据源是否完备,是决定框架修复能力上限的一个重要的因素。
上面解决了埋点错埋和多埋的问题,但是不能解决埋点漏埋的问题。解决埋点漏埋需要在交互的合适时机,计算好埋点字典传输给SDK。计算的问题上面已经解决。那么只要满足在合适的时机计算,就可以解决埋点漏埋的问题。
综上所诉,如果要修复埋点问题,则需要满足下面三个条件:
-
能够无二义性的识别错误数据。
-
完备的数据,可以计算出正确的数据。
-
需要在合适的时机进行计算。
其实对于错埋和多埋的修复场景,就是在上报SDK前这一时机进行计算。
至此,一个解决埋点热修问题的计算框架原理基本完成。框架主要围绕三件事情展开:
-
一,向JSContext补充API提供基础计算能力。
-
二,补充数据源为计算提供物料。
-
三,补充触发计算的时机。
计算、数据、时机是一个计算框架能力最重要的三个因素。为了进一步说明,下面给出一个修复加购埋点漏埋问题的案例。
随着提供的API、数据以及时机能力增强,该框架可以解决一些线上功能性问题修复。比如:
-
修复视频多段拍摄存在问题:在进入剪辑编辑器前修改传入的音轨信息,禁用多段拍摄功能,并调整页面相关控件的显示状态。
-
修复搜索特定关键词,导致富文本渲染出现崩溃:修改下发数据字段,回避崩溃问题。
-
修复因缺少参数,导致品牌非自营商品搜索请求失败:修改接口的请求体,补充必要数据。
-
修复SKU切换时某区域数据未刷新问题:在SKU切换后,重置该区域的View的显示状态。
此外,还进行过一些数据实验。比如分析5秒内用户退出APP的原因,UT通道数据丢失指标建立等。
对计算、数据、时机三个维度的补充,框架已经从埋点修复,泛化为一般的端计算框架。通过控制数据,去影响APP的功能。从端计算的角度看JSPatch等热修框架,它的计算、数据层面限制较少,但是修复时机是函数调用级别。相比代码行级别的修复,框架对修复方案有一定的限制。
二 从端计算角度改善DinamicX框架
DinamicX的搭建能力非常强,一般情况下,模板主要从单一数据源取数计算。数据源通常由网络请求下发。
如果期望做一些接口胶水层聚合,或者定制客户端ViewModel的逻辑,可以接入FAAS层对DX的数据源进行重计算。
但是FAAS只能利用服务端侧数据进行计算,从端计算角度看,无法天然使用客户端侧数据进行计算。这样并不适应需要服务端侧和客户端侧数据共同计算的需求。比如有些展示坑位有红点提示,需要点击后让红点消失,或者消失后隔一段时间再次展示。这个需求客户端侧相对好实现一些,坑位点击后本地打标,也不需要消耗服务端资源。服务端也有一些方案,比如点击后发起请求由服务端打标,然后FAAS层根据标记计算数据源展示。或者客户端打标,在请求时回传标记给服务端,然后由FAAS层计算数据源展示。两种服务端方案,本质上类似,都是想办法让服务端侧获取这个标记数据。
不想消耗服务端资源,又想从DX层面实现这个需求,如果看了之前埋点热修的框架方案,很自然的得出下面的解法。
这个方案是可以解决上面的问题,但也有一些设计上的问题。比如纯动态化发版解决有些麻烦,逻辑分散,客户端会有额外的内存、IO操作。回到问题本身,其实我们是期望在DX引擎渲染计算时能够利用服务端侧和客户端侧数据。我通过对DX框架的学习,发现一种更优雅解决该问题的方案。
虽然DX渲染接口上只能使用单一数据源,但是DX提供了DataParser自定义计算表达式机制。我们可以定制一个DataParser,在模板渲染中使用客户端侧数据。这样DX模板其实可以支持多种数据源进行计算。同时DX提供了一个用户上下文,用于参与DataParser和EventHandler的计算。我们可以设计一个DataParser,获取用户上下文中的键值对数据;此外可以设计一个EventHandler用于将键值对数据设置到用户上下文中。用户上下文提供多种生命周期的存储方法,实现页面内DX组件间数据互通,页面间DX组件间数据互通,以及持久化能力。从时机角度看,其实DX可以在事件触发时,执行多个EventHandler。这样可以通过组合执行EventHandler代替类似万能函数的EventHandler实现。使计算更具有灵活性。最终改造后的方案如下。
新方案通过计算和数据两个角度进行了优化。方案不额外占用服务端资源,在DX模板中实现了全部逻辑,同时支持动态发布能力。比较优异的解决了该需求。
三 端计算优势以及未来发展
计算上云目前是趋势。极端的角度看,期望客户端越做越轻,将主要的计算能力放到云上解决。我之前做过类似云游戏的方案,3D游戏这种极端依赖客户端硬件能力的应用也可以上云。随着通讯技术的进一步发展,游戏上云、APP上云将来会有商业化产品出现。虽然趋势如此,但是端上依然有两大优势,是云计算无法替代的:一是算力经济性,二是数据完备性。
从算力经济性角度看,端设备硬件的算力逐渐攀升。一般使用场景,算力其实是过剩的。同时频繁、大数据量的通讯,无论对用户还是运营组织,都是存在成本的。云计算与端计算未来会因经济性和体验,在适用场景上达到一个平衡。这是整体计算经济性最优导致的结果。
从数据完备性角度看,端上采集永远是第一手数据,无论维度还是数据量都较大。这些数据传输,以及在云上还原用户上下文场景都需要巨大的算力。云端获得数据前,需要端上处理、清洗数据。云端数据始终存在人为的信息丢失、修改情况。可计算性依赖数据完备性,另外出于对响应、算力的考虑,有些计算场景下放到端上计算更合适。特别是一些需要大量、复杂用户上下文数据参与的场景。此外,未来隐私合规升级,数据传输到云上会更为谨慎。为了保证一些服务的可持续运行,需要提供端计算的适配方案。
服务端和客户端都满足数据完备性的情况下,如果客户端再提供计算动态性支持,其实选用哪个方案没有本质性区别。例如FAAS服务可以使用云计算实现,也可以使用端计算实现。剩下的是性能、体验、成本以及稳定性等其他方面综合性考虑。