JSPatch 被禁?你的 APP 需要另一种发布模式!

阅读 1069
收藏 17
2017-03-09
原文链接:www.appadhoc.com

灰度发布

让iOS开发群炸锅的消息

今天一大早看各个iOS开发群炸锅了,原来是苹果大佬禁止了热更新和JSpatch。导致很多人的项目上线和更新被拒,目前还没有解决方案。Apple官方警告如下:

app灰度发布

影响广泛,各路英雄一脸懵逼

13

什么是JSPatch?为什么人多开发者乐此不疲?

JSPatch 是一个 iOS 动态更新框架,只需在项目中引入极小的引擎,就可以使用 JavaScript 调用任何 Objective-C 原生接口,获得脚本语言的优势:为项目动态添加模块,或替换项目原生代码动态修复 bug。

APPLE为什么要这么做?

践行自己生态圈大管家的角色,iOS 社区早就有不允许动态更新的条例,只不过一直睁一只眼,闭一只眼罢了,谁知开发者视苹果爸爸为无物,蹬鼻子上脸,竟然演进除了JS Patch 和 React Native的黑科技。终于暴露出了大问题,去年的关于iOS漏洞的报道:

ab测试
可见,黑客正事利用了热更新框架的漏洞,攻击证书发行商,进而获取临时证书,终于苹果爸爸生气了。说到这里,真替 react native 捏把汗…
针对修复bug,动态发布模块的强需求,硅谷FLAG的最佳实践是什么?

 

以Facebook 为例,Facebook的David Wei写了一篇文章《代码和产品发布的几种方式》明确分析了下几个概念:

 

1、灰度发布:也可以称为分步代码发布,是一种代码发布的方式。基本操作是整个团队共用一个代码库,一定频率(比如每天一次,或者每周一次)把整个代码的最新版本做一个新的发布分支(release branch),把发布分支逐步发布到产品线。

2、AB测试:这是一种很成熟的概念,是产品发布的常用手段。比起分步代码发布,AB测试往往有更长的周期(比如几个星期甚至几个月)。基本操作是产品的开发者加一个或者多个配置控制(一般每个产品配置应该带有配置的ID),允许通过调节相应的配置来让一个产品发布到“逐步选择”的用户群。

 

覃超大魔王介绍过Facebook使用的一大法宝就是灰度发布和 A/B测试。这一利器像宙斯盾一样(想不出更好的比喻),多次将Facebook从出错的悬崖上拉回来。

 

Facebook早在2007-2008年就在网页服务端(PHP)上开发了这套发布和测试系统,代号叫 GateKeeper (最早在Boz的文章中提到),本质上它就是一个开关,可以在一个admin page上定义一个个的开关,然后控制某些开关到底是开还是关。这些开关的属性预先都缓存在内存中,所以读取开关的操作不重。示例代码如下:

15

主要的逻辑就在 if 中,判断这个开关是否对相应的用户开启,如果是则跑实验代码,否则跑老代码。非常直接和简单对吧!后来,Facebook又陆陆续续对它进行了各种加强,让其可以更加精细地分割和控制用户,比如说 对于US的1%用户开放,或者对于日本的年龄25岁以下的男性用户开放等等。可以从时间,国家,加入日期,好友数,是否为FB员工,性别,年龄等等各种维度进行控制。

16

这极大方便了我们对于用户分批进行 A/B测试

 

Gatekeeper(简称GK)对于Facebook的整个internal tools组来说一个很重要的基础设施。随着Facebook用户量的增大,每个GK每日的被访问量也大大增加;同时Facebook自己的功能和相应的GK项也不断增加, 这对于整个GK的规模能力后来也提出了很大的挑战。

 

到了移动时代后,iOS和Android的 core team 也相应地推出了比较强大的移动灰度发布和 A/B测试 工具,代号叫做 Airlock ,其中我们的一位中国工程师也参与它的开发。当然,类似的工具还有不少,比如 Twitter 开源的 Clutch IO 。移动上的 Airlock 系统稍微复杂一点:

 

首先,用户在手机上登录或者打开Facebook App后,airlock会从FB server取得所有的GK值;然后在本地缓存起来;
然后在 iOS 或者 Android 代码里写相同 if 判断逻辑,来检查当前用户是否已经开启这个属性。是的话,跑试验代码,否则跑老代码;

 

然后App每隔一段时间去和server同步一次(FB用的是一个小时的间隔);当然App随时也可以强制去取server上的最新值。

 

最关键的是:移动端的logging会把当前用户的每个GK的值记录在logging中,这样当这些logs被上传到server后, server可以根据这些logs来统计用户的GK值和相应的动作。

 

Facebook 每次更新App大小都将近200M,产品Roadmap中近期可能上线发布的功能都已经打包在其中,同时在本地代码加入一个库,来负责和server同步所有开关的值,以及在logs里记录好相应的这些开关,便于后来分析用户的行为,来了解此用户是暴露在怎样的开关组合中。

 

下面来看个案例:

Facebook iOS App的演化

下面来说一下iOS下面的Facebook App界面演化过程。众所周知,Zuck 和 Steve Jobs 的私交一直不错,Zuck 也把乔帮主当做自己的模样,私下里经常去乔老爷家里共进晚餐和请教 run company 的窍门。所以,用 iPhone 第一版SDK开始,Facebook就有iOS原生应用开始入驻App Store:

app ab测试

可以看到iOS还是拟物化的风格,Facebook用的是当年红极一时的九宫格首页。消息提示在首页的最下面,当时Facebook还没有 Like button,只可以comment。此版本的Facebook App为最初一版,由一大牛独自完成。此大牛把后来的常用组件开源成 Three20 库。

 

后来Facebook经过一次大的UI改变:

18

最大的变化就是九宫格改为了左侧抽屉式的导航栏,左上角出现著名的”Hanburger”按钮。
于是来到2013年,Facebook App准备进行新一轮的大改版,由左侧抽屉式改为 Tab bar 格式:

19

这一版的改动,在意义上主要是让用户可以更加方便切换到news feed以外的其他功能区;可是却引发了另外一个问题:到底下面的tab bar放几个按钮?每一个位置上应该放什么?

110

此时已经是2013年,前一年在Facebook在WWW首页的改版失败依然影响着公司的engineering team,于是在iOS App决定更偏好保守和务实。Airlock在这次的改版上起到巨大的作用。Facebook iOS core team的人写好了tab bar的代码后,并没有马上发布给所有用户,而是开始了长达4个月的灰度发布和A/B测试。

 

测试了下面 tab bar 各种可能的情况:比如 5个tab项 或者 4个? 第二个放 Requests or Messages? Notifications 或者 Groups 暴露在外面? 同时对于右上角的按钮的功能和样式也进行了测试,比如是放 通讯录 还是 Messages? 是放一个图标还是直接写字?等等。

 

一度因为出现新的测试组合,以及对于好几个组合的测试结果在数据上的比较模棱两可而把发布时间一拖再拖。整个iOS App界面重组的项目由 Mick Johnson 主导,他是我见过执行力最强的Facebook的几个PM之一。他认真审视了各种组合的数据后,结合Facebook当时要大力推行Messenger的大背景,最后确定上图的组合顺序。这个组合在各种测试中数据的综合表现最好,能够有效地让用户查看news feed,增加用户的好友数(好友数是从Facebook data组里试验出来的一个非常重要的指标,这在文章最后可以和大家介绍),方便地收发消息,以及查看新消息,但是 groups,events,还有其他一些辅助功能被藏入了 “more” 之中。

 

综合来看,灰度发布 (shadow release) 和 A/B测试的特点和注意事项:

前端代码预先发布;且有可能同时多套不同版本的代码存在;

移动端或者前端MVC的代码需要按照一定频率获取来自服务器的控制信息,从而展示相应的形态;

后台可以对发布进行精密的控制。

 

比如说:发布给多少比例的用户,用户所在区域等;并且即使在开放给100%用户后,只要 GK检查 没有清楚,则server仍然可以远程控制(或回滚)试验中的功能。在某些严重bug出现的情况下,可以完全回滚某一功能。

 

注意:由于有A/B测试的原因,不同用户A和B坐在一起,都刚刚下载和安装了最新的Facebook App,但是打开App后所看到的功能(甚至UI布局)却可能不一样;并且对于同一用户,今天看到的App里展示的功能可能和明天展示的也不一样,即使他并没有更新自己的App。
苹果爸爸已经放大招了,如果你可以搞定灰度发布的话,恭喜你!继续潇洒吧!如果搞不定的话,也许吆喝科技的解决方案可以帮到你。

评论