如何通过热修复,搞定开发中的那些 Bug?

发表于2016-07-01
评论0 2.2k浏览
  作为程序员,Bug 修复终究是绕不开的话题,本期移动开发精英俱乐部讨论的主题便是 Bug 修复中的 Hotfix,即热修复。接下来让我们跟随大牛的脚步来了解 Hotfix,就算你不能一下豁然开朗,相信也一定会有所启发。非常感谢赖春辉的整理,本文系国内 ITOM 管理平台 OneAPM 审校。

一、什么是热修复?
  主持人-牛树民:我们自己的项目中还没有这方面的技术方案,最近一直在考虑这个。大家对热修复这个名词是怎么理解的?什么是热修复?
  七里小晴天:是不是跟游戏打补丁差不多?
  longway:运行时,改变运行行为。
  王威威:对已发布 App 进行 Bug 修复。
  罗飞:边开发边修复?修复 Bug 时不影响正常开发?热补丁的主要优势是不会使设备当前正在运行的业务中断,即在不重启设备的情况下可以对设备当前软件版本的缺陷进行修复。——百度百科
  主持人-牛树民:从广义的角度理解,大家都比较认同 Hotfix 是在移动端不需要重新发版,通过在线更新对版本 Bug 的修复。

二、使用 Hotfix 的团队都有哪些?
  王威威:目前有多少公司已经用上 Hotfix 了?
  七里小晴天:12306的增量更新,算不算?
  李程:百度贴吧是热修复。
  罗飞:我们使用 git flow,它有 Hotfix 的机制,我一直认为 Hotfix 只是修改 Bug 并不影响正常开发, 应该广义的 Hotfix 范围比这更大吧?
  主持人-牛树民:大家在自己公司的项目中有使用过热修复方案的吗?有经验的欢迎来分享一下。
  李道建:只是最近刚看 JSPatch ,【推荐文章 JSPatch – 动态更新 iOS App http://www.cOCoachina.com/ios/20150709/12468.html】
  主持人-牛树民:好像微信团队有在使用 JSPatch,这个还没有求证。网上说,滴滴也开始在使用了。

三、如何实现 Hotfix ?
  不会凉的黄瓜菜:热更新和增量更新是一个东西吗?
  王威威:不一样,增量更新是 Patch, JSPatch 是动态更新吧?
  李程:热更新就是替换啊,替换整个函数。替换类太大了,一般都是替换方法。
  李道建:我感觉确切应该是替换某个方法或类。
  longway:类,也有替换方法的,不是函数。
  李道建:都可以,根据线上的Bug而定。
  主持人-牛树民:在游戏开发者一般采用的JS,Lua解释性语言,通过下载代码的方式,在技术角度上是一种热修复。
  李程:一般修复Bug,都是某个函数的问题,如果函数错的很多也别惹修复类了,直接再发一版了。
  智:在移动 App 开发里,可以动态部署达到热修复。例如某页面出现了 Bug ,后台服务器修改配置为采用 React Native 显示此页面,而有 Bug 的 Native 页面就隐藏了。等到下一次版本更新发到线上渠道,再采用 Native 展示此页面。
  主持人-牛树民:我的理解 React Native 更像是一种更新。运行时修复在 iOS 和 Android 中具体都有怎么样的体现呢?
  李程:运行时修复不用等待App重新启动,iOS 利用运行时特性修改函数地址,从而达到修复目的。
  Neuropathy:那这样的话移动开发中的热修复好像不容易吧,不重启也可以么?
  李程:是的,要是重启就是冷修复了。
  李道建:反正我在官网上下载一个 Demo,用 JSPatch 也是需要重启。
  kyleduo:我觉得重启这个问题可以不用太纠结,即使需要重启,能稳定修复线上问题也是可用的,毕竟对于严重的 Bug 来说,不在于及时修复。
  海:我们做了基于 JSPatch 的定制开发,也可以做到不重启App就生效。
  智:主要热修复,我感觉就是因为发到线上的客户端,是没法及时修改的,但是服务器可以随时控制。
  longway:需要服务端深度配合,发布版本及时自动化,还是有些麻烦。
  李道建:假如移动App线上有问题,应该是是从服务器下载某些文件,再通过运行时机制来替换有问题的代码吗?
  longway:对,一般是个补丁包。
  A RunningYoung:App 的线上 Bug 可以采用轻量级的修复吧,如 JSPatch 要是大规模热更新或者采用RN 吧。
  李道建:最近看 JSPatch,大体就是这样的思路。
  智:比如 iOS 下的 JSPatch , WaxPatch ,Android 下的 Dexpose,AndFix ,ClassLoader 都是比较成熟 Hot Patch 动态部署解决方案。这些方案的思路都是通过下载远程服务器的代码来动态更新本地的代码行为。
  A RunningYoung:感觉代码质量好了,用个轻量级的就可以修复严重的Bug了。
  一毛:Deposed 和 Fix 都不能全部适配,各自的方案都有自己的优缺点,classloader 可以发挥更好用途,局部的更新倒是采用 andfix 这样类型的方案,感觉比较方便。
  超:Hotfix 版本管理策略怎么说呢?
  李程:JSPatch 就解决了啊,JSPatch 就是通过 JS修改原生代码。
  王伟:我们 Lua ,JSPatch 都用到了
  海:iOS 的 Patch 是比较成熟了,可以用。
  主持人-牛树民:Lua 和 JSPatch 哪个好些呢?
  王伟:我觉得用 Lua 顺手,但是他有些问题在 Block 中用的话,引擎之前有过64位的问题。
  海:阿里巴巴解决了64位的问题
  王岳明:是的,Wax 被阿里接手后修复了这个问题
  王伟:JSPatch 我们年初上的,下发策略用的一套方案,我们用的场景不多,除非重要线上Bug,Lua 引擎最近我们更新都一年多了。
  李道建:你们需要重启 App 吗?
  王伟:不需要重起。
  海:我们打算用 classloader 方式 不过貌似必须重启 App。
  A RunningYoung: JSPatch 也必须重启才生效 ,然后替代本地的 OC 代码。
  主持人-牛树民:Hotfix 的用途也就在此吧。
  一毛:Lua 在游戏中运用比较多
  王岳明:JSPatxh 为什么要重启?是运行时桥接啊。
  王伟:确实,游戏中使用场景多。
  主持人-牛树民:游戏中更多是更新游戏模块等, 在应用开发中用于 Bug 修复吧。

四、下发策略
  主持人-牛树民:大家讲讲的下发策略吧。
  王伟:我说下大概吧,我们有个 sync 接口,会下发当前版本是否需要下载 Lua 包。如果有就启动下载,下载后会进行校验。
  李程:你指的 sync 接口是?
  AFI:那是全量下载 Lua 包吗?
  李道建:校验是避免重复下载是吗?
  王伟:然后加载脚本,到指定类时运行。我们目前是针对版本号做的,可以理解这个版本下的全量下载,校验是防止被篡改。
  李程:肯定不能全量下载,每个 JS 补丁包都有个 ID 号的。下发策略,主要是本地与服务器制定的协议如何设计了,增量应该是没问题的,每次全量下载肯定不太好,我们项目就是通过 App 版本号与 JS 补丁号来进行增量取的。
  主持人-牛树民:校验的方式都有哪些呢,MD5 值和加密?
  AFI:如果只是热修复,问题并不大。
  李程:校验方式肯定自己家项目设定的了,防止别人抓去接口,随意给恶意修改函数。
  主持人-牛树民:对,怎么保证在下发代码执行过程中的安全呢?,有可能因为疏忽下发了有问题的代码,导致大量 App Crash,或一些其他异常情况,需要有一些机制避免这种情况。
  李程:设定自己的校验协议。
  海:例如方法 a 在主线程执行,方法 b 在子线程执行,如果这两方法都有 Bug 要 Patch 就不行了。
  王伟:我们会在本地测试好,QA 通过验证后才正式发送修复脚本。
  拯救与逍遥:灰度热更新。
  李程:这就是需要一个健壮的 Server 与 App 之间的协议了。
  王伟:而且内部模拟下发全流程操作测试。
  主持人-牛树民:我觉得可以针对部分用户做下发代码更新,做一个灰度验证。
  Neil.zhang:其实,Android Studio 2 的 Preview 版本中体现的Instant Run功能,本质上也是一种热修复技术
  Miracle:用 cordova angularJS 框架的应用,大家都用 JSPatch 做 Hotfix 吗?
  阿尘:我用 JSPatch.com 的方案,首屏不能实时更新,需要重启。其他地方的都可以。
  AFI:那React Native 和 Hybird 比,大家怎么选?【推荐文章:Hybrid App 和 React Native 开发那点事
  阿尘:JSPatch 是修复 Native,Hybrid 本身就可以有动态性,不应该在讨论范畴。
  阿尘:大家可以看看,JSPatch 作者分享的干货
  主持人-牛树民:是的, RN 方案本身是作为更新程序功能来使用。
  阿尘:据小道消息,阿里也在尝试 JSPatch了,和 Wax 结合使用。
  林曦:为啥要和 Wax 结合使用呢?这两种方案有互补的地方?
  阿尘:两种都支持吧。JS 比较受欢迎,也可能 Wax 有些缺陷,还未考证。使用 Hotfix 可能面临的问题,就是多线程。
  海:JS 和 Lua 都是单线程的,这是硬伤。
  AFI:嗯,确实,但也提供了一些模拟多线程的办法,不过在性能上跟 Native 还差些。
  海:不是简单的性能问题,如果要同时修复两个线程的方法就悲剧了。
  李程:修复两个线程的方法 ?
  来海龙:要是多线程的话现在有解么?
  主持人-牛树民:JSPatch 近期新特性里有讲到,已经解决了这个问题。
  海:我们是做了多实例,主线程独占一实例,安卓Patch就没有多线程的问题,不过就是碎片化的问题严重,jni 在不同的 rom 上实现标准不统一。

五、适配与性能影响
  kyleduo:我比较关心的问题,1,Hotfix 会不会影响性能;2,对 Android 来说,会不会有机型不支持,不支持的体现是什么会不会导致 FC 或功能不可用。
  拯救与逍遥:1,基本不影响 2,适配是大问题,有些方案不兼容5.0。
  kyleduo:之前调研过,也是说5.0的问题,现在5.0已经比例很大了,所以不敢用。
  拯救与逍遥: 女娲的原理是支持5.0的,但是我没有试过 ,据我所知,这个原理是原QQ空间团队的一个人做出来的。
  kyleduo:百度到的:基于 Nuwa 实现 Android 自动化
  
六、App Stores审核
  主持人-牛树民:使用 JSPatch 在 App Store 审核上会有问题吗?
  李道建:网上说 JSPatch,Apple 已经认可。
  幸xing:没问题,很多大厂也用了。
  主持人-牛树民:JSPatch 官网平台有 SDK 集成和代码部署的整套方案
  
七、Swift能否实现 JSPatch?
  刘志淳:Swift 有类似 JSPatch 类似的实现么?听说 Swift 混合 OC 调用 JSPatch 有问题?
  海:Swift 有点尴尬哦,这个坑没踩过。
  Server:Swift 调 JSPatch 有点坑。
  刘志淳:好吧,Swift 做主力开发的只能打酱油了。
  罗飞:Swift 怎么解决?
  海:Swift 默认取消 OC 的动态性,当然也有办法让 Swift 方法采用 OC 的编译方式,感觉还是不方便。

八、noark9:动态的地方要用 OC 才行。
  刘志淳:混编这么形式我觉得始终是临时解决方案,Swift 目前没有靠谱的 Hotfix 解决方案?
  阿尘:Swift 本身 Runtime 不行,目前没有靠谱的 Hotfix 方案。
  PS:大道千万,何必死磕动态特性?就算 Swift 是静态语言,也有许多方法让其灵动起来,我们无需让其强行实现 Objective-C 的特性,那样就失去 Swift 自身的特点了,Objective-C 终究会成为过去式,苹果也不建议这么做。——Swift 脑残粉
  腾讯GAD游戏程序交流群:484290331Gad游戏开发核心用户群

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引