移动产品热更新的功能指标和实现架构

来源:互联网 发布:永恒之塔人物数据 编辑:程序博客网 时间:2024/05/22 00:10

前言

热更新能力是影响产品运营效率和用户留存的关键能力,本文根据卓盟信息科技CTO王志海在七牛架构师实践日上海站上的分享,介绍了卓盟旗下产品乐变热更的产品设计、技术原理、理论基础和架构,帮助大家更好的实现产品地优化。


我今天是来跟大家分享一下两个方面的内容,一个是我们的热更新是怎么做的,原理是怎么样,第二个是围绕我们这么多年的经验,也可能是有哪些坑,包括遇到问题是怎么解决的。希望是对在做热更解决方案的朋友能有一些帮助。


一、热更新的整体架构

首先,给大家介绍一下我们热更新的一个整体的结构。客户端是这样的,首先我们热更新的进程放在一个独立的进程里面,这样的好处是什么?如果我们的客户端刚启动就crash了,一样能热更新保证可以修复,这也是一定要放在独立进程里面的一个原因。大家容易有一个误解,是不是放在独立进程里面就是后台常驻进程?其实这个不是这样的,进程只是在需求的来去时运行它,可能我们的一个APP的大小是30M,有可能是下载的一个内容是3M左右,如果网速是在400-500K的话,可能下载的时间也就几秒钟,整个从下载到更新完也就是1,20秒。所以放在独立进程里面并不会增加系统的负担。带来的好处是客户端crash了之后我们一样可以把这个问题给修复。提供给运营人员使用的可以是浏览器或者PC的工具,把版本是传到管理后台,管理后台根据它传过来的包计算与之前版本的一些差异,把结果是存在DB里去,就决定了这个包进来之后升级的一个路线,360渠道的包进来升级360的版本,应用宝的进来升级应用宝的版本,然后客户端这边是访问Portal的这个Sever给他返回一个有没有新版本,如果有新版本再通过CDN网络去下载,比如用七牛的CDN就可以解决。这边都是比较成熟的一个方案。


二、热更新的客户端实现介绍

再看一下我们的实现的机制。IOS是禁止热更新的,所以我们主要谈一下安卓。需要更新的内容,一个是代码(Java,C/C++),一个是资源,还有安卓比较特殊的四大组件。四大组件是系统安装进来的时候就决定了,所以说我们不能增加,这样很麻烦,你的功能是会限的很死,一会我会详细的给大家介绍我们怎么能做到新的版本里可以新增新的组建,它的原理是怎样的。各个部分的更新有不同的方案,Java部分可以通过ClassLoader去把它给替换掉,native的部分我们可以通过修改ClassLoader的nativeLibraryDirectories,或者代码里直接loadLibrary的方式来调用新的libary也是可以的。资源这一块也是有多种的方案,比如I/O Remapping或者通过自定义的ResourceManager加载进来都是可以的,组件这一块我们等一会再说。JavaHook也是一种方案,但是他的复杂度是会高很多,有JIT之后会更加复杂,很多时候是运行时候编译的。这一块我们也有成熟的方案,但还没到可以商业化的程度。

我们的热更新的方案,是下载之后会把完整的新的版本都还原出来,还原出来之后也涉及到一个问题,当有新版本的时候,会对新版本进行一系列的管理,包括四大组件的管理,包的管理,资源管理等等,其中四大组件生命周期的管理是很重要的一部分。


三、热更新架构与Android系统的关系

安卓里面的各大组件之间,Systerm Server 之间的通信,很多都是通过Binder来通信的,所以我们可以在客户端这边做一些代理,从而改变APP运行时候的执行路径,通过这个方式可以动态的把整个新版本加载起来运行。


四、新增组件处理机制

下面就给大家详细的介绍一下如果新的版本增加一个Activity,我们是怎么做到的?首先,系统能够看到的一定是已经在安装的这个包内定义的一个组件,如果我们第一个版本只有一个Activity,那第二个版本增加了一个Activity,应该怎么做呢?

首先第一步,先在AndroidManifest.xml里面定义一些组件。可能大家这里会有一些疑问,其实我们不知道会增加什么组件,包括名字我并不知道,其实没有关系,这里只是一个占位符,我们只要定义放在那里就可以了。举一个例子,比如说我们新的版本,增加了一个ActivityA 。第一步也就是我们刚才说的在第一个版本里面定义一些预留的组件,这里我们定义的是ProxyActivity。第二步,当新的版本去启动ActivityA 的时候,首先客户端这边,在进程起来的时候我们会做这样的一个代理,相当于把这个客户端的ActivtyManager改成了我们自己的实现,在startActivity的时候我们会把这个intent里面本来它是要启动ActivityA换成我们预先定义的Proxy Activity,然后到了AMS那边,它可以看得到,这个Activity已经在版本里面定义了,所以它是能够正常工作的,它调用ScheduleLaunchActivity的时候,它回调回来的是我们刚才改过的Proxy Activity,但新的版本里没有ProxyActivity这个类,所以我们得再把他改回去,改成原来有的ActivityA,所以我们会把ActivityThread里面的Callback换成我们的,然后在handleMessage里面再把msg.obj.intent这个类名再换回原来的,这样ClassLoade里面就能找到ActivityA了,后面的都可以正常工作了,这就是新增组建很关键的一个地方。是不是一定要在AndroidManifest中定义ProxyActivity呢在某些情况不需要的,我们是可以复用,如果我们新增的这个ActivityA和之前的Activity有相同的theme/process属性,其实我们是可以是复用他之前的Activity,因为对于系统来说仅仅是一个名字而已,只要找到他就可以了。


五、热更新的实践经验

1、热更新的主要特点和指标


给大家介绍一下我们这么年做热更的经验和心得。一个好的热更方案,应该包括哪些功能,每个功能会遇到什么问题,这些问题我们是怎么解决的?相信这些会对大家有一些帮助。主要涉及的点有几大方面,包括可更新的范围,用户的感知程度等等,那我们就逐一的把这些给过一下。

(1)可更新的范围

更新的范围就是我们刚才所提到的,有这么几大块,Java代码,native代码,资源,组件。其实是当前市面上有很多热更的方案,或多或少都有一些地方都不能更新,不是说不能用,所带来的问题是什么?第一个,做版本更新的时候会小心翼翼,就是我不确定我这次更新的东西会不会导致和之前的版本不兼容。比如只能更新Java代码,组件不能更新,新版本中新的Activity,之前你没定义的就会有问题。当然也不是所有东西都能更新,它是受限于系统的,举个例子来说像权限就是受限制的,如果你的第一个版本没有定义权限,那新的版本下来的话,这个权限是没有办法获取的。当然这个问题解决不了不等于说它是一个问题,我们是可以通过其他的方案,比如说我们在它在传版本的时候我们就来校验他新老版本的一些权限是否有新增的,给它一些提醒,能预防的问题也是解决问题的一个方法。

(2)差分能力

第二块是差分能力,可以使用BSDIFF/BSPATCH,这个算法是MD5匹配的,也就是说我们的代码没有任何的更新,只是重新编译一次,用户安装了两个不同版本的包,如果我是基于第一个版本做的差分包,其实第二个版本打不上去的,因为它的MD5已经变了。这里所常见的问题是什么?大家通过应用商店更新APP的时候经常会有这样的体验,有的时候它是会提示你,一个100M的包你下10M就够了,有的时候要下100M才可以,这是什么原因造成的呢?主要是渠道那边会对我们传到应用商店李的包会打一些标记,比如说我传到360的包,它为了跟踪APP的活跃情况,包括用户的付费等等,它在移动端,Web端的手机助手上的包是不一样的,基于一个版本做的差分包是不能打到别的上面去。这个问题我们是这样解决的,我们使用的一个叫文件级差分的方式,我们会把这个新老版本的包给解开,我们会计算里面每一个文件的差异,再把这个差异发回客到户端,再来去把它还原。如果我们发现你的包的MD5没有,跟我服务端提上去的包不一样,我们会把这个包相关的每个文件信息传到服务器,根据它和这个服务器已有的包的差异,重新生成一个差分包,我们把它叫做远程的一个差分计算的方法。有的时候,我们会发现,同样的版本是改动的并不大,但是差分包的算法差别很大。是因为两个版本之间的压缩的等级不一样,这个时候如果你直接拿整个包来算的话,可能算出来的差分包的大小和你原包的大小是很接近的。那这个解决方案也是类似的,也是通过这种差分的方式,把包解开之后,再去逐个算里面文件的MD5,这个方法理论上面是能够是做的很小的,但是当前有一个弊端,因为新的版本是在客户端重新合成apk的,所以有一些信息是会丢失,MD5和原来传在服务器上的MD5是不一样的,有些加固的算法可能会校验这个包的MD5,所以这个是一个平衡,在你的差分包大小和安全性等等方面找了一个折中。

(3)用户感知度控制

更新版本的时候相信大家有这样的体验,比如说大家玩游戏的时候,游戏有一个新的版本需要资源内更,进来之后也不管你是什么网络就直接给你下载了,对于用户来说这并不是一个特别好的体验。另外就算是Wi-Fi的网络进来之后,可能用户也不一定想更新。一个良好的一个用户感知的体验应该是,如果是要消耗用户流量是要告知用户,在Wi-Fi网络下我们尽可能的把自动的更新给做掉。另外一个方面呢,当我们的新的版本更新完之后我们可以是给用户一个推送,说明新的版本有那些功能让用户来体验,合理的适度的推送是对用户的推动是有提升的。

(4)AB测试和灰度发布

借助版本的更新我们可以做一些AB测试和灰度的发布。比如说有一个新的功能,这个新的功能到底怎么做并不是我们的产品经理拍脑袋决定的,要看数据说话的,那这个时候应该怎么做呢,我们会把不同实现的策略都把他做好,让不同的用户去更新不同的内容,然后我们再对比哪个方案更好。常见的问题:第一,要把采样埋点预先设计好。有可能是我们的数据出来了,这个方案的数据会更好,但是如果第一次采样点埋得不够,我们就不知道是到底是什么原因。第二,我们在对比的时候只对比一个维度,如果说AB两个方案,每个方案是有三个纬度,可能A的总的数据比B更好,但是A可能并不是最优的方案,有可能A里面第一个点是好的,但是其他两个点比B更差,所以说维度多了会有一些干扰因素在里面,出来的结果不一定是客观和最优的。第三,样本的选择要公平。常见的一个错误,想试两个功能到底怎么样,在A渠道试A方案,B渠道试B方案,这个并不是那么准确,因为不同的渠道用户的属性是有差距的,你在不同的渠道试不一样的功能,出来的结果不一定准确和客观。这个解决方案有两种,一种是叫做客户端随机方法,一种是叫服务端随机方法。客户端随机有客户端决定客户端具体的表现。服务端随机的方法就是,我给客户端随机的下发不同的版本来更新。他们各有优缺点,客户端随机的方法它把用户网络的差异很平均的给随机了,服务端随机的优点是可以把数据差的那个方案的用户给更过来就可以了。具体选择哪种可以根据大家实际的需要来选择。第四,样本的数量要足够,如果说样本不够的话,遇到的常用的问题是数据会反复,第一天我发现A的方案更好,第二天变成B的会更好。和AB测试类似的是灰度发布,当我们有新的版本准备上线的时候,不要让所有的用户都更新,我们可以是先小批量的试一下,没有问题的话是再让所有用户更新是会更好。

(5)精细化更新

除了版本更新之外还应该提供一些更加精细的控制,这里举了几个例子分别来说明适用于哪些场景,解决哪些问题。第一,我们可以按照机型或者系统的版本更新。为什么有这个需求,相信大家都有遇到这样的情况,经常有一个BUG在某个特定的机型或者是特定的系统版本才有,最好的解决方案是我只更新有问题的用户,你更新的越多越容易出错。如果我们很确定这个问题只在那一个机型那一个系统版本出现,我们就只针对这个机型来修复,不想干的用户就可以不走这个更新过程。第二,我们可以是根据用户的不同来更新不同的版本,比如用小米手机就有这样的一个特点,如果你用的是稳定版本,它是不会给你做自动更新的,如果你用的是开发版本,那一周可能要给你更新两次。第三,可以按照不同的区更新。比如一些O2O的产品,它很多都是跟线下门店有一些活动的,可能这次在广东有活动,下次在上海有活动,在这种情况下他们可能希望在广州做活动时只有广东的用户看到这个功能,而不是所有的用户都更新这个功能之后看到只有广东的用户来参加,这样的体验不好。最后一点,如果我们能够对用户进行一个准确的画像,理论上可以根据不同的标签把不同的用户更新不同的版本。比如在游戏领域完全可以做到我为大玩家用户来定制一个版本,让他玩的更爽。其他玩家我也可以更新更加适合于他们一些版本。

(6)版本退回

版本回退是指出现紧急情况下,可以先回退到一个能正常工作的版本。具体有两个表现:如果安装的就是要回退的目标版本,这种情况下我只需要让他启动老版本就可以了。还有一种情况是用户直接安装的就是新版本,我们会做一个逆向的差分,原来我们是从A到B算一个差分包,现在我们反过来,就可以直接把新版本更新为老版本,带来的好处是我可以快速的响应,运营人员只需要在后台操作一下,告诉他会退到哪一个版本就可以了。而不是让开发去紧急的查看这个问题,基于之前的代码来打一个包,版本控制如果不是那么的严格,会容易出问题。

(7)运营支撑能力

那最后再给大家介绍一下,定时上线和预下载这个两个很实用的东西。比如说双十一的快到了,如果我们想针对双十一开发一个特殊版本,让用户能在那一天就看到新版本的这些功能,我们可以怎么做呢?我们可以在后台设置一个到双十一零点能让所有用户看到这个版本,走应用商店的问题是没办法保证每个渠道过审的时间是怎样的,使用热更的方案的话,所有的控制都是掌握在自己手上,可以自己决定用户什么时间看到这个新版本。结合定时上线这个功能,还有一个,一般而言我们建议跟预下载一起用,如何去用呢?比如说我们为双十一准备的版本,一般会提前一个星期做好了并通过了测试,在这种情况下我们可以让用户在无线环境下就已经下载这个版本了,但是这个版本并不会生效,是等到双十一零点定时上线以后,已经下载的用户会自动切换到新版本,没有下载的用户会提示他有个强更。如果这个时间比较长超过一个星期,根据我们上面介绍的这个情况,一般而言,95%的用户在一周之内会连一次Wi-Fi,一个星期的时间绝大多数用户都会更新国新版本。


2、各种热更方案的对比


那最后是一个简单的和各个热更方案的对比,我们就不详细介绍了,总的来说,乐变的热更新方案是最牛逼的!

我的分享就到这里,谢谢大家


原创粉丝点击