微信号:freshmanTechnology

介绍:一群技术人的天地,每周3定期在线分享,覆盖各大城市,不怕起点、不惧权威!中生代创造未来!

【阿里鬼道】Weex在双11会场的大规模应用:业务支撑、稳定性保障和秒开实战

2016-12-27 13:20 鬼道

鬼道(徐凯),就职于手机淘宝基础架构团队,曾为天猫Pad客户端TL并负责天猫Web前端架构。就职百度移动推广团队期间,负责开发Android/iOS推广SDK、统计SDK,及对应的Web管理站点。

前言

Native   开发的诸多亮点中,流畅体验和系统调用是最多被提及的。流畅体验体现在页面滚动/动画的流畅性,背后是更好的内存管理和更接近原生的性能;同时又是   Web   的痛点:资源首次下载、长页面内存溢出和滚动性能、动画性能、传统   web   性能(如JS执行效率)。Native   有丰富的系统调用能力,而   Web   痛点在于:W3C   标准太慢,有限的设备访问能力,API   兼容性问题较严重,如   Geolocation     Android   Webview   中可用性很差。

Web   开发同样有诸多亮点,其中最耀眼的当属发布能力和规模协作。Native   App   商店审核周期长(尤指   iOS);应用更新周期长,iOS   稍快大概能达到一周更新率   60%-80%,Android   同样的更新率要2周甚至更长。而   Web   在合适的缓存机制下一分钟可达到   99%+。浏览器内核   webkit   提供了相对一致的底层运行环境,html/js/css   控制页面的结构/行为/样式,uri   连接不同的页面,有了这些基础设施,大规模的业务复用和人与人的分工协作变得相对轻松。 同时今天阿里诸多客户端已经面临包大小接近临界值,大促活动页面(H5)体验较差等一系列问题。结合   Native     Web   技术亮点,同时又能解决阿里遇到的业务问题,这就是   Weex   诞生的客观环境。 2016.11.11,在   1754   张双11会场页面中(统计了天猫和淘宝),Weex   页面数为   1747   占比   99.6%。手淘   iOS/Android   分别有   83.5%/78.3%   版本(UV)启用了   Weex   会场,手猫   iOS/Android   分别为   91.7%/87.9%   版本(UV)。Weex   覆盖了包括主会场、分会场、分分会场、人群会场   等在内几乎所有的双11会场业务。 在这样的应用规模下,工作和目标是: 1.   业务支撑,支撑住双11需求,这是最基本的要求,详见下文“业务支撑”一节 2.   稳定性保障,Weex   引发的问题第一时间响应并处理,不留到双11当天,详见下文“稳定性数据”一节 3.   秒开实战,稳定当先力争高性能,双11正式主会场秒开率冲到   97%,所有会场秒开率冲到   93%,详见下文“秒开数据” 2016   双11会场的感受可查看原始录屏文件: WIFI   |   4G   |   3G   |   2G   |   无网络   。录屏时主会场已经是预加载版本,其中   WIFI     4G   效果接近,2G   效果取决于数据的网络请求速度(录屏时数据请求约3.9s),无网络情况下打底数据来自前一次成功请求。流畅性可查看 该视频,左起为   H5、iOS   Weex、Android   Weex。

1 目标

展开   Weex   双11细分目标:

  -   Weex   双11细分目标 2 业务支撑

支撑住双11的业务需求,是   Weex   必须要迈过的坎。 双11的会场结构大致为:会场框架(框架   +   主会场、全部会场、必抢、清单、我的双11)、分会场、其他会场(分分会场、人群会场等)。

3 会场框架

Weex   支撑双11业务首要解决的是会场框架及其交互形式:

1.   交互主流程: 1.     push   方式(框架Tab   切换):主会场   -   全部会场   -   必抢   -   清单   -   我的双11 2.   push   方式:主会场   -   分会场   -   主会场 2.   iOS   考虑到内存开销,需严控打开的主分会场weex页面,定为   n   级可配,默认为   5;同时   iOS   会场框架为单实例,也是出于内存的考虑;Android   连续打开   30   级以上   Weex   页面,未见内存异常增长,无需特殊方案

  -   会场框架交互 Weex   会场框架很好支撑住了双11的复杂交互需求并提供了更好的内存管理。除了会场框架,更多的   Component     Module   支撑住了各色各样的双11需求,这里仅列出几个代表: 1.   List   组件是几乎所有会场页面的标配,流畅的滚动帧率、高性能的内存复用机制和渲染机制是页面流畅体验的重要基础 2.   Animation   尽管是实验版需求,却支撑住了会场的垂直弹幕、坑位显隐等动画效果,动画效果细腻 3.   Weex   点播/直播组件     全景图组件支撑住了更为垂直个性化的业务需求

4 组织结构

上节内容也可以看出,参与   Weex   双11会场涉及多个团队和平台系统:

  -   Weex   双11中组织结构 1.   天猫业务:通过斑马(活动页面搭建和发布平台)发布会场页面 2.   淘宝业务:通过斑马和   AWP   (产品页面发布平台)发布会场页面,上层   DSL   使用   Rx(即将开源) 3.   预加载:提前将会场   js-bundle   下载到客户端,客户端访问   Weex   会场时网络   IO   被拦截到本地文件     IO,从而极大加快了网络加载速度,预加载是这次秒开实战的抓手(注:最核心的工作) 4.   手淘、手猫客户端,Weex   是客户端的一部分,客户端中其实是   Weex、Native、H5   并存的 5.   Weex   SDK、业务模块:Weex   容器和基础的   Components、Modules,业务模块包括直播/点播组件、全景图组件 以上也仅涉及到客户端和发布端,背后还有无数的业务后台系统,就不一一列出了。   Weex   架构自上而下地展开: 1.   Business,Weex   业务层,Weex   双11主战场是手淘和手猫,此外还有大量客户端已经启用或接入了   Weex 2.   Middleware,Weex   中间件层,包括为   Weex   页面提供发布(斑马、AWP)、预加载(AWP)、客户端接入支持(AliWeex)、组件库(SUI)、游戏引擎、图表库等模块;其中斑马、AWP、预加载都直接参与了双11 3.   Tool,工具层 1.   DevTools,界面和交互复用了   Webkit   Devtools,支持   elements、network、断点、console   2.   Playground,方便开发者调试   Weex   页面,同时也是   Weex   example   的聚集地 3.   Cli,Weex   命令行工具集 4.   目前仍在建设更多的工具,如   weex-pack   支持一键打包成   App 4.   DSL 1.   JS   Framework,Weex   最初的   DSL   是基于   Vuejs   1.0   语法子集;目前在社区中在推进基于   Vuejs   2.0   的版本 2.   Rx,基于   reactjs   语法的   Weex   DSL(将于12   月正式开源) 5.   Engine,渲染引擎,从架构设计上,Android/iOS/H5   RenderEngine   是相互独立和平等地位的渲染端,这是保持三端一致的基础,当然在协议实现层面需要更多的设计、质量保证

  -   Weex   架构

以上就是   Weex   在双11中的架构和业务支撑的范围了。 5 稳定性保障

Weex   的首要挑战就是稳定性,或者说保障   Weex   会场最大限度不降级。 6   iOS   JSCore   内存治理

8月初(同期双11启动)奥运大促时,手淘   iPhone   中反复进出会场20+(手猫15+),会出现   crash。奥运大促当天,手淘   iOS   1.59%   crash   次数来自该问题(top   6),手猫1.94%(top   8)。发现问题的当天成立了攻坚小组,从   JS业务代码、JSFM(框架)、iOS   渲染、iOS   JSCore   几个方向同时排查,一周内各方向排查到逐步收敛到:根本原因是   Weex   页面实例被全局持有(weex   runtime   只有一份),进而导致页面退出时内存不被释放,反复进出直至内存爆掉。因而任何可能导致页面实例被全局持有的因素都会触发这个问题: 1.   业务代码中的问题,意外导致的,给出   Lint   工具扫描业务代码,引入了“全局污染治理”(见下一节) 2.   JSFM   框架中的问题,如在   destroyInstance   时清理   commonModules   和所有   dependency   target;iOS7下的   Set   Polyfill   内存飙升问题 3.   iOS   中的问题,通过下发配置控制   VC   Push层级控制;内存警告时的非当前实例销毁策略,加入开关控制;iOS   9.x   JSCore   原生   Promise     Polyfill   并存时的内存问题

除了建立攻坚团队推进解决该问题,也在造势期前就展开双11会场压测,反复验证该问题,自双11造势期会场开测之后,该问题未再出现。 7 全局污染治理 在治理   JSCore   内存的过程中,逐步意识到对全局变量管控的必要性。Weex   中多个页面共用   1     runtime,单个页面如果写法不规范不仅可能导致内存泄露,更有可能污染全局环境,进而导致所有   Weex   页面无法正常工作。全局污染治理的核心抓手:

1.   严格模式,即   `use   strict`,使用严格模式可以将较多常见的   JS   陷阱转化为错误,如:无法再意外创建全局变量、将拼写错转成异常、限制了   eval   的能力  

2.   冰冻对象,利用   ES5     `Object.freeze()`,将   Weex   核心对象和   JS   原生对象“冰冻”住。尝试修改被“冰冻”的对象会抛出错误,一旦“冰冻”无法“解冻”。 8 跨端依赖梳理 Weex   通过   Adapter   来适配不同客户端的具体实现,诸多通用库,如:网络库、图片库、API   库、   H5容器(Web   组件)、埋点库、配置库   等在不同客户端上版本不一致,因此导致的线上问题将会成为双11会场的隐患。为此展开的依赖梳理和同步机制是双11稳定性的保障之一。这件事情可能将会长期出现在   Weex   问题清单之中,如何做到上层   Weex   SDK? 9 会场压测

*   压测场景 1.   5     200   坑位的普通会场页面,1   全景图会场页面,1   UT   Expose   压测页面,1   直播会场页面 2.   页面中提供链接,能够按顺序进行   push   跳转 *   压测方案 1.   主链路(首页->店铺->详情->购物车)做一遍操作,让内存缓存占满,记下内存值   M0 2.   进入   Weex   页面,滑动到底部,滑动到顶部,记下   M1;点击跳转按钮,跳转到下一个页面 3.   重复步骤   2,让所有的页面进行压栈;全景图->p1p2p3p4->直播->p1p2p3p4->UT *   压测结果:iOS   通过,Android   通过 1.   测试过程手淘手猫均未出现因为压栈导致的   Crash,稳定性可以保证; 2.   Android低端机压栈过多会导致体验较差,之后也会引入类似   iOS   VC   层级控制;

压测在造势期会场测试阶段展开,在超出真实会场压力的情况下(真实会场150坑位上限),尽可能提前嗅探出潜在的   iOS   JSCore   内存问题、iOS/Android   异常闪退等细节问题。 10 稳定性数据 2016.11.11,Weex   在手淘中的   Crash   占比情况:

*   iOS   1.46%(TOP7) *   Android   Java   Crash   0.85%(TOP13)、Native   Crash   1.72%(TOP8)

考虑到会场的业务量级,Weex   的稳定性仍然是不错的。注:单独计算的   Weex   Crash   率太小,参考价值不大。 11 秒开实战 Weex   秒开率   =   (加载时间   +   首屏渲染时间)<   1s   的比率

其中:加载时间指   Weex   js-bundle   的加载时间(从网络下载或本地加载);首屏渲染时间指   Weex   页面开始渲染到第   1   个元素   bottom   超出首屏范围的时间。下文提到的“首屏网络时间”为加载时间与首屏渲染时间的和。

从双11结果看预加载大幅度提升加载时间,对秒开率的贡献尤其突出;但性能优化是个长期迭代的过程,回头来看优化的抓手是:预加载和首屏渲染优化。 12 预加载

预加载解决了   1   个问题: 用户访问页面(H5/Weex)之前,将页面静态资源(HTML/JS/CSS/IMG...)打包提前下载到客户端;用户访问页面时,将网络   IO   拦截并替换为本地文件   IO;从而实现加载性能的大幅度提升。

启用预加载后加载时间的变化,粗算一下:手淘   iOS,走网络平均   296ms,走预加载   18ms,网络性能提升约   15   倍;手淘   Android,走网络平均是   696ms,走预加载是   54ms,网络性能提升约   12   倍,但绝对值更大,对   Android   会场秒开贡献更为突出。 2015年预加载已经在双11   H5   会场中有较多应用,2016   年预加载升级为一项基础服务,不仅为   WindVane   提供预加载能力,也成为   Weex   秒开的最强外援。 此次双11会场共启用   30   个预加载包,总容量超过   20MB,业务需求相对稳定且流量较大的几个页面(会场框架+主会场   等)是独立的包,保证了对整体秒开的贡献,其他分会场均分在剩余的包中。同时主要采用强制更新的策略,即新的资源包(服务端有新发布)未下载到本地就直接读取线上,可以保证业务的实时性。2016.11.11,双11会场中   Android   走预加载占比为   59.4%,iOS     62.5%,高于平均水平(但还可以更高)。

13 首屏渲染优化

首屏渲染优化的目标就是尽力缩短首屏的渲染时间,为此在一系列的优化过程中,可以粗分为:DOM   解析优化、UI   渲染优化、分段懒加载。 13.1   DOM   解析优化 *   Component   append   属性定义了   `node`     `tree`   2   种渲染模式,`node`   就是逐个节点渲染,   `tree`   就是整棵树一起渲染。直观的对比: node   |   tree *   `node`   模式,节点逐个从   js   提交到   native   的,   native   侧有个   16ms   间隔的   layout   保证渲染的正确性,这是更接近于   WebKit   的一种解析渲染模式。优势是每一个被解析完的节点都可以立刻显示,同时保证不会长时间阻塞主线程,劣势是可能会造成多次冗余   layout,拉低流畅性。 *   `tree`   模式,整棵树(以当前节点为   root   的整棵树)从   js   提交到   native。优势是只需布局一次,渲染更高效;劣势是如果   tree   过大,就可能会阻塞主线程甚至阻塞渲染。 *   `node`     `tree`   可以精细化地控制页面展示的逻辑和颗粒度,典型的实践为首屏以内按   tree   解析,首屏以外按   node   解析。 13.2   UI   渲染优化 *   List   组件在   native   分别对应   iOS   UITableView     Android   RecyclerView,这两种   View   构建了   App   的半壁江山,使用它们来封装   list   的好处: *   只会渲染可见区域,减少首屏的渲染消耗 *   内存复用,所有滑动到不可见区域的   cell   都会被系统回收,用于渲染下一个   cell *   cell   之间天然互相隔离,   可以默认以   cell   维度划分并用   tree   的模式解析,提高渲染效率 *   拥有原生的交互体验,在   cell   上点击、左滑、右滑、移动排序等交互方式后续可以更方便地支持 *   想要达到   60FPS   的体验,一次主线程渲染必须少于   16ms。Weex   中一次渲染需要经过   6   个主要步骤(Build   Tree、Compute   Style、CSS   Layout、Create   View、Update   Frame、Set   View   Props),所以必须在   16ms   内完成这   6   个步骤,现实是任何一步在主线程中都可能超过   16ms,这块。 13.3分段懒加载 *   除了底层的优化,业务上也通过分段懒加载进一步降低整体渲染时间,对首屏渲染有间接帮助(减少调度) *   方案为:会场页面使用   List   进行布局,一个   cell   对应一个模块;页面启动默认加载   6   个模块(少数页面因为首屏模块过多因此特殊处理);默认往下滑到底触发   loadmore   后再加载   5   个模块;若加载过程中遇到电梯则电梯以下模块全部加载 除了底层的保障,我们也坚持每天产出“性能优化建议”,推进业务性能优化,接下来会有更加方便的工具提供给业务方直接性能调优;如双11期间   devtool   中增加了层级检测和告警,可以帮助排查深层级导致的   android   低端机   stackoverflow。

14 秒开数据

由于主会场流量占据了总流量的大部分,对其秒开率单列统计。2016.11.11   数据为:

主会场

  • 秒开率峰值(00:00):整体   96.9%(278.8ms)   ios   99.4%(146.4ms)   Android   93.4%(411.1ms)
  • 秒开率均值:整体   94.4%(367.6ms)   ios   99.0%(177.0ms)   Android   91.8%(473.3ms)
  • 帧率(FPS):红米   Note1s   53、小米5s   58.5;iPhone5c   53.1、iPhone6p   56.9、iPhone7   58,帧率数据来自线下采集,见 视频(左起为   H5、iOS   Weex、Android   Weex)。
所有会场
  • 秒开率峰值(00:49):整体   92.4%(490.7ms)   iOS   97.4%(291.6ms)   Android   87.5%(689.8ms)
  • 秒开率均值:整体   83.9%(651.9ms)   iOS   94.5%(368.0ms)   Android   78.6%(797.4ms)

15 新的起点

Weex   技术委员会在十月中成立了,核心解决   Weex   开发过程中的标准化和协同问题。并于10.26   进行了第一次会议,审议的   4   个话题(Input   focus/blur、750px实现方案、weex   analyze后续发展、标准化流程草案)经过充分讨论,均获得全员投票通过。 鬼道作为第一任组长,接下来半年带领各方推进   Weex   在集团和社区的深度建设,欢迎大家参与   Weex   的共建之中。对于参与   Weex   的各方而言,最直接的影响就是:需要作为   Weex   官方推荐,向集团或(和)外部社区贡献的   Module、Component、工具、平台   等成果   需要通过   Weex   技术委员会检视标准性。要求在   方案设计出来后实现之前   和(或)   实现出来后     2   个时间点向   Weex   技术委员会汇报标准性相关细节;这个要求是强制的,目的是保持   Weex   社区的标准化推进。如果你只是为局部业务开发定制化的   Weex   扩展,不涉及标准性,并不会被要求到   Weex   技术委员会汇报。 Weex   任重道远: 1.   Weex   不只是   Weex   容器,Weex   业务背后是发布、预加载、AB、线上监控、质量效能度量、数据埋点、业务开发技能转变/升级   等一系列行为的交织,如何减少业务从   H5/Native   转向   Weex   时的“阵痛”,是接下来的攻坚重点 2.   双11中遇到的典型案例或问题,会成为下一阶段的工作重点之一 3.   仍有大量业务需求需要开发,为此我们已经启动了   Weex   BigBang   项目,按照   WindVane     API   的调用频度和业务反馈情况,分批实现   30+   Weex   Module/Component,包括常用的   schema   唤起支持、网络类型判断、geolocation、audio、cookie、大图预览、通讯录   4.   减少新客户端接入   Weex   的成本,目前在尝试的   AliWeex   项目会扩大应用范围并成为客户端接入的标配 5.   跨客户端的底层依赖不同步问题会一直存在下去,需要更好的解法 不一一列举了,之后会有   Weex   Roadmap   的讨论并且会及时公布出来,欢迎关注。 从“ Native     Web   融合”开始,先后经历的   Hybrid、React   Native、WVC   再到   Weex,这段经历也算挺戏剧性的;未来会是   Weex   吗?答案并不重要,唯有沉醉其中。


本文节选章节于2016双11电子书

记录阿里巴巴2016双11背后的技术

欢迎扫描识别上图二维码阅读全书



 
中生代技术 更多文章 IT精英们和网红们周末都去哪了 圣诞节最值得关注的六个技术公众号(文末有福利) 老曹眼中的敏捷开发【中生代北京闭门会实录】 融数CTO王东谈从0到1打造有战斗力的全栈团队【中生代北京闭门会实录】 浅析无服务器的微服务架构与实践
猜您喜欢 他山之石:2016年创业者怎么做好一款手游? 史上最“基情”的开班——现场惊现花样美男五人组!更有年少基友现场表演心灵感应 MIUI 设计主管:MIUI 6 是怎么诞生的? 中移动LOGO换新颜 重塑企业品牌 如何在面试中识别一个坏老板