醋醋百科网

Good Luck To You!

每按一次升级的小红点,软件就开始变身

在互联网不太普及的时代,很多软件公司还是会发布离线更新包,这种更新包其实就是个安装程序,只是安装的内容是更新的部分,没有变化的文件直接用已经安装的版本的。此外这些安装程序还会修改一些系统配置以适应新版本的功能,比如注册 COM 组件,修改注册表等。

现在互联网已经十分普及,几乎所有软件都采用在线升级,具体实现上,有下列几种做法。

1. 比较简单的,通过 http 协议,检测是否有更新,就是把本地版本号发给服务器,服务器会返回一个配置文件,里面表明是否有新版本,并且带有新版本的下载地址,更新程序按照 URL 下载新版本的安装程序,然后执行这个安装程序,用户根据安装程序提示进行更新。

2. 再进化一步,每次都重新安装太麻烦,更新程序下载一个新版本的压缩包(zip/7z),然后帮用户解压缩到安装目录。现在客户端都追求简单设计尽量降低和系统的耦合,基本都是复制文件就算安装的那种绿色软件,所以把新版本的文件一更新就能用。

3. 如果某个软件体积已经比较大了,比如大于 10MB,每次都下载一个完整的新版本的话,下载就太慢,安装也慢。既然本地已经有个安装版本了,每次更新其实变化的东西也不是很多,那么有个软件就下载一个更新文件的压缩包,然后解压缩到安装目录覆盖旧文件。

4. 有的软件更大,更新也频繁,每次更新的 exe dll 模块大多都有更新,所以还是要下载很大的更新包,于是有人用 bsdiff 算法求新版本和旧版本的二进制差异,如果新版本就是修了 bug 改了几行代码,那么 bsdiff 生产的补丁也就几 KB,下载的二进制补丁用 bspatch 来更新本地版本。bsdiff 的算法库很小,大约才 30+KB 很容易集成到更新程序里。

5. 有的软件更更大,即使用 bsdiff 产生的补丁还是很大,有人搞出了更给力的补丁算法,Chrome 的方法,
http://dev.chromium.org/developers/design-documents/software-updates-courgette

从介绍看,它比 bsdiff 生成的补丁还要小一个数量级,这个想法相当巧妙,对于那种代码模块为主的程序尤其有效。很多时候我们只改了几行代码,但是 DLL 模块却改变了很多,主要是因为代码优化链接时重排造成的,如果比较汇编代码差异就会很小,Courgette 就把 DLL 反编译成汇编码,然后和旧版本的汇编码比较得到差异,更新的时候把旧版本也反编译打补丁然后再编译成 DLL。这样的话如果只改了几行代码,那么生成的补丁可能就几十个字节。

6. 随着更新包越来越大,更新下载和安装的时间也越来越长,造成用户长时间等待,有的软件采用了后台下载后台更新的方式。所谓后台下载就是无论用户是否点了立刻更新,只要有新版本就在后台偷偷给用户下载下来,有点流氓,但这也是为了用户体验呢。那么后台更新呢,正在运行的程序,每个文件都是被占用的,是不能更新的。还是 Chrome 想出来的,双目录更新,把就版本先复制到另一个目录,然后更新这份新复制的,下次用户启动的时候就直接启动新版本。

比如 Chrome 有如下的目录结构

Chrome
    +Application
        +35.0.1916.153
        +35.0.1916.114
         chrome.exe 

它用版本号做目录名,每次升级的时候更新新版本,旧版本在另一个目录运行不受影响。下次启动的时候 Chrome.exe 永远加载最新版本的 dll 运行就好了。chrome.exe 是个很小的程序,里面的逻辑就是检测下版本号加载最新版本的 dll,这样简单的程序本身几乎不需要更新。

在需求的推动下,现代客户端的升级程序已经相当复杂了,包括了支持灰度放量的新版本检测,http 断点续传下载,MD5 完整性校验,bsdiff/courgette 二进制补丁更新,双目录迭代升级等技术。到了移动 app 时代,以上这些技术都用不到了,操作系统垄断了升级机制,只能通过操作系统检测下载安装更新,iOS 做得相当彻底,Android 还给 app 留了条自己下载 apk 安装的路,但是二进制补丁完整性校验等就彻底不需要 app 开发者自己操心了。

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言