PC客户端软件升级方式简史

  • 在windows8以前,微软的Windows平台一直没有提供一个想苹果的AppStore或者Linux的包管理这样的统一软件管理工具。因此Windows下的软件安装、升级、卸载的事情通常都是软件本身去负责。这样致使Windows下的软件安装、升级、卸载的方式五花八门,但整体上来讲方法都大同小异。安装程序主要分两种,下载器的安装包和离线安装包,这个不赘述。
  • 今天重点聊一下升级,升级功能看似简单,但对于一个想持续经营的客户端软件来讲倒是一个重要的生命线。开发团队辛苦修改的bug、作的新功能都但愿用户能立刻经过升级新版本体验到。
  • 在互联网还没普及的蛮荒年代,不少软件公司升级都是发布离线升级包,通常这种包就是一个安装程序,它只负责安装程序须要更新的部分,而后作一些修改注册表之类的系统配置以适应新版本的功能。
  • 如今互联网普及后,全部的PC客户端软件基本上都是使用的在线升级。git

    • 最简单的在线升级方式是首先客户端发送检测更新的消息到服务器,服务器给返回是否有新版本,最新版本号以及下载地址等信息,客户端就根据这些信息处理。若是有更新就去刚刚获取到的地址下载最新的安装程序,而后执行安装程序更新。
    • 后来你们以为每次都从新安装太麻烦,并且安装包也特别大,下载也很是耗时。因而这个下载的程序被替换成了一个压缩包,里面装的是程序须要更新的文件。升级程序下载好压缩包后再解压到安装目录中就完成了软件的升级。
  • 随着敏捷开发方式的普及,软件的升级就变得愈来愈频繁了。对于PC客户端软件每次升级时主程序以及一些重要的动态库都有可能更新,因此下载的压缩包也会比较大。因而就产生了比较文件二进制差别的算法BsDiff,以及Google基于其进一步改进的Courgette(小胡瓜)。这些算法的加入可让补丁包缩小了n个数量级。这样须要客户端去下载的压缩包就会很小了,下载耗时也会大大缩短。
  • 另外值得一提的是,随着软件升级包大小愈来愈大,用户下载更新文件的等待时间也愈来愈长,因而有些软件就采用了后台静默下载的方式。这种方式虽然流氓,但可能对于用户来讲体验要好一些。那么这种状况下主程序通常都还在运行,而升级程序下载完成后想要更新文件当即升级就必须关闭主程序而后进行文件替换,以避免文件被占用,致使升级失败。因而Google的chorme搞出一个双目录更新的方法来应对这种状况。所谓双目录更新就是把原来的文件先复制到另外一个目录下,更新程序的时候就更新这个文件目录,升级完成后就直接重新的目录中启动新版本。
  • chrome的目录结构是这样的:
Chorme
    +Application
        +57.0.2987.110
        +57.0.2987.88
            chrome.exe
  • 能够看到,他是以版本号作目录名。之后启动chrome.exe时去加载最新版本就能够了。固然它能这样作主要由于chrome.exe自己是个很小的程序,基本它自身是不须要升级的,它主要负责的就是检测版本号而后加载新版本的dll。
  • 固然如今的客户端升级程序还涉及一些入灰度,md5完整性检测断点续传等技术这里也不在赘述。下面我简单介绍一下BsDiff和Courgette。
BsDiff: Linux中的一个开源工具,致力于快速和轻量的更新Linux的操做系统漏洞(跟微软的安全补丁相似),其算法的核心思想是基于统计学规律进行近似匹配,而后经过一系列的变化(好比BWT变换)提升“近似段”的压缩率。
Courgette: Google Chrome升级系统的核心模块,基于BsDiff,但对其进行了一系列的改进,将平台相关的信息(即x86汇编指令)融入其中,以指望更精确的定位指针,从而避免统计算法在差别明显时候的错误率。
  • Google官方给了一个10M的升级包例子使用bsdiff能够看到包小了很多,用Courgette更是少了几个数量级。

  • 使用bsdiff算法咱们的升级过程是这样的:
server:
    diff = bsdiff(original, update)
    transmit diff

client:
    receive diff
    update = bspatch(original, diff)
  • 大体流程就是这使用bsdiff算法比较不一样版本的二进制文件制做补丁包,客户端下载补丁包后调用bspatch生成新的二进制文件。
  • 使用Courgette的升级过程是这样的:
server:
    asm_old = disassemble(original)
    asm_new = disassemble(update)
    asm_new_adjusted = adjust(asm_new, asm_old)
    asm_diff = bsdiff(asm_old, asm_new_adjusted)
    transmit asm_diff

client:
    receive asm_diff
    asm_old = disassemble(original)
    asm_new_adjusted = bspatch(asm_old, asm_diff)
    update = assemble(asm_new_adjusted)
  • Courgette对于bsdiff的优化主要就是在adjust这一步上,具体能够参考Courgette官方说明
  • 最后,Google还开源了一套Windows下的升级协议,你们有兴趣也能够研究下omaha
相关文章
相关标签/搜索