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

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

    • 最简单的在线升级方式是首先客户端发送检测更新的消息到服务器,服务器给返回是否有新版本,最新版本号以及下载地址等信息,客户端就根据这些信息处理。如果有更新就去刚刚获取到的地址下载最新的安装程序,然后执行安装程序更新。
    • 后来大家觉得每次都重新安装太麻烦,而且安装包也特别大,下载也非常耗时。于是这个下载的程序被替换成了一个压缩包,里面装的是程序需要更新的文件。升级程序下载好压缩包后再解压到安装目录中就完成了软件的升级。
  • 随着敏捷开发方式的普及,软件的升级就变得越来越频繁了。对于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更是少了几个数量级。

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

  • 使用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
点赞
收藏
评论区
推荐文章
blmius blmius
4年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
Wesley13 Wesley13
4年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Peter20 Peter20
4年前
mysql中like用法
like的通配符有两种%(百分号):代表零个、一个或者多个字符。\(下划线):代表一个数字或者字符。1\.name以"李"开头wherenamelike'李%'2\.name中包含"云",“云”可以在任何位置wherenamelike'%云%'3\.第二个和第三个字符是0的值wheresalarylike'\00%'4\
Wesley13 Wesley13
4年前
FLV文件格式
1.        FLV文件对齐方式FLV文件以大端对齐方式存放多字节整型。如存放数字无符号16位的数字300(0x012C),那么在FLV文件中存放的顺序是:|0x01|0x2C|。如果是无符号32位数字300(0x0000012C),那么在FLV文件中的存放顺序是:|0x00|0x00|0x00|0x01|0x2C。2.  
Wesley13 Wesley13
4年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
4年前
PHP创建多级树型结构
<!lang:php<?php$areaarray(array('id'1,'pid'0,'name''中国'),array('id'5,'pid'0,'name''美国'),array('id'2,'pid'1,'name''吉林'),array('id'4,'pid'2,'n
Wesley13 Wesley13
4年前
(绝对有用)iOS获取UUID,并使用keychain存储
UDID被弃用,使用UUID来作为设备的唯一标识。获取到UUID后,如果用NSUserDefaults存储,当程序被卸载后重装时,再获得的UUID和之前就不同了。使用keychain存储可以保证程序卸载重装时,UUID不变。但当刷机或者升级系统后,UUID还是会改变的。但这仍是目前为止最佳的解决办法了,如果有更好的解决办法,欢迎留言。(我整理的解决办法的参
Wesley13 Wesley13
4年前
Java日期时间API系列36
  十二时辰,古代劳动人民把一昼夜划分成十二个时段,每一个时段叫一个时辰。二十四小时和十二时辰对照表:时辰时间24时制子时深夜11:00凌晨01:0023:0001:00丑时上午01:00上午03:0001:0003:00寅时上午03:00上午0
Python进阶者 Python进阶者
2年前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这
Dart
Dart
Lv1
九月九日眺山川,归心归望积风烟。
文章
4
粉丝
0
获赞
0