Dec29

【原创】 APK增量升级架构设计分享

Author: leeon  Click: 8462   Comments: 2 Category: 架构  Tag: apk,android,增量更新,增量升级

       众所周知在国内应用发行领域增量升级技术做的最棒的当属应用宝,从apk的增量升级覆盖度和增量文件大小上都提供了近乎完美的实现方案,应用宝基本上可以涵盖用户90%以上的安卓软件更新提醒,可以说在国内其他大型的应用发行商店都无法做到应用宝这么广泛的增量升级体验,那么应用宝到底是如何实现这一架构的呢?

      应用宝采用腾讯自研的一套移动终端sdk开发框架和服务器通信框架来实现基础的网络通信功能,这样的设计方式完全区别于其他的安卓应用发型架构。豌豆荚,百度手机助手,91,以及360手机助手都没有实现二进制流的加密通信,都是json+http的方式来通信,而应用宝实现的是完整的HTTP二进制流的通信方式,这样我们是无法轻易获取应用宝的上下行通信数据,那么应用宝又是如何来实现应用的增量升级的呢?

     腾讯应用宝的数据除了提供给自身使用外,还提供给android版本的腾讯浏览器客户端使用。刚好腾讯的浏览器在对用户安装的软件做分析并上传服务器的整个过程中是没有做很严格的数据加密,可以抓包反向分析出腾讯是收集的用户安装的apk文件中的manifest.mf文件。大家都知道apk文件中manifest.mf文件代表了整个apk的文件指纹,他和加密数据一道构建了apk的完整签名,来保证软件的有效性。网上流传的各种增量升级方案都是依赖于完整apk的bsdiff解决方案,这种方案必须依赖于一个apk包的md5值得完全匹配,如果整个apk包有解压和再压缩的过程,那么狠容易导致整个包中的实际内容没有变化,但是重新压缩后的apk文件md5值变化,这就导致了bsdiff在合并的过程中失败。而腾讯的巧妙做法就避免了apk再次压缩的问题,完全精准的定位了一个apk包的版本特性,那就是收集每个apk保重的manifest.mf文件的md5值。

    大家都知道apk的应用包之所以很难做到增量升级是因为太多的渠道包,太多的同版本不同内部文件而导致差异化的包分发太广,服务器端无法完全收集到所有同版本的软件包来做增量文件的计算。笔者这里给出一个巧妙地方法,那就是在用户的终端上来收集manifest.mf的完整文件内容上传到服务器端,同时比对服务器端的最新版本APK包的manifest.mf文件中每一行的差异化数据,来判断用户客户端的旧版本和服务器端的新版本的差异文件,这样就可以获取到用户端的需要升级的差异化文件,从而保证了在服务器端不知道旧版本的情况下能智能分析输出差异包,应用宝之所以能支持几乎所有软件不同渠道的增量升级,我想他们的做法很有可能是在客户端的后台有定时的推送机制,就算没有支持到用户的增量升级,他们也可以做到异步的后台分析和计算,在用户下一次请求更新提醒接口时获取到增量升级的文件数据。

    那么又有人会问,为什么应用宝可以用一个增量升级文件来支持到非常多的渠道升级呢?他们的做法我想也就是同一个老版本不同渠道的manifest.mf文件的互相比对,来找出差异数据的合集,这样就保证了差异文件的最大共性化,再和新版本的文件进行比对,获取到最终的增量升级文件。

    服务器端计算增量升级文件的大致架构就是如此,其实并不难,主要就是如何收集用户的manifest.mf文件数据。又因为应用宝庞大的发行量,他们很容易收集到大量广泛的渠道apk包,因此大部分用户在收到升级提醒的时候都能做到增量文件的下载。

    那么客户端又如何支持到增量文件的安装呢?笔者如上所述的内容完全有别于网上一大堆bsdiff,xdelta的方案,因此必须实现自己的一套增量文件合并算法。笔者已经实现了一套高性能的apk合并算法,通过实际测试,合并性能和应用宝的增量升级的合并性能旗鼓相当,同时通过大规模的测试可以得出生成的增量升级文件的大小几乎和应用宝的增量升级文件一致。对于低端手机在增量升级安装过程中的性能和内存消耗和应用宝别无二致。其实这里的实现很简单,就是利用zip文件结构的特殊性,来重新组装增量升级文件和用户手机中的apk文件,利用java本省的nio特性来加速合并apk的过程。

    说了这么一大堆,还会觉得应用宝很难搞定了么?其实你也可以做出一款堪比应用宝的增量升级功能了。

Nov5

【原创】在zend studio中添加第三方库

Author: leeon  Click: 5223   Comments: 0 Category: php  Tag: php,pecl,zend studio

好久没碰PHP了,最近温习一下,下载了最新版的zendstudio来体验。在编写引用第三方库的接口时,zendstudio往往不会那么智能,导致无法自动提示代码,和代码检查。zendstudio本身就是eclipse二次开发的,可以支持到include path的配置。那么我们使用pecl的memcached第三方库做为示例来讲解如果在我们的PHP工程中正常调用第三方库接口。

下载pecl的memcached第三方库,解压目录后可以获取到memcached-api.php文件,这个就是此扩展的接口定义。我们将此文件放入新创建定义的third目录下。

配置libraries: 点击选择windows-> preferences ->PHP-> Libraries 

点击New新增:输入库名,这里我们统一定义一个第三方库集合。勾选add to environment。

新增后,选择新增项然后点击add external folder ,这时候会弹出目录选择窗口,选择关联到先前创建的third目录。

创建好libraries后还是不够的,我们需要在工程中进行关联:

选择工程点击右键,选取include path -> Configure include path 

在选项卡中选择Libraries,然后点击Add Library ,在弹出的窗口中选择刚才我们创建的third 即可。

此时在我们的工程中就可以正常引用第三方库了。

备注: 通常在pecl的扩展包中都会有一个php接口文件,我们添加接口扩展都可以用到此文件。




Aug23

【原创】MyBatis Generator使用小记

Author: leeon  Click: 16609   Comments: 1 Category: java  Tag: mybatis,generator

最近在新的项目中使用Mybatis提供的generator工具来自动生成代码,为了提高效率,我是用mybatis提供的eclipse插件来生成代码,在使用过程中遇到一些问题,在此记录下来:

1. 默认mybatis generator会在生成普通代码同时附加example的示例代码,通常我们不需要这些东西,生成出来清理也麻烦,可以在generator的xml配置文件的table配置项中添加

enableCountByExample="false"

enableUpdateByExample="false" enableDeleteByExample="false"

enableSelectByExample="false" selectByExampleQueryId="false"

来关闭example代码的输出。

2. 工具在eclipse中使用有可能会提示jdbc找不到,这时候在配置文件中添加classPathEntry配置项即可,将mysql的jdbc包引用进来,类似如下配置:

[code="xml"]
<classPathEntry location="C:\Users\leo\.m2\repository\mysql\mysql-connector-java\5.1.26\mysql-connector-java-5.1.26.jar"/>
[/code]

3. 配置文件中commentGenerator配置项最好不要设置为不生成注释,因为这样带来的问题是在自动生成的代码上不会存在@mbggenerated 这样的标记,这个标记是用来标注这些代码是代码生成器生成的,如果关闭了注释,我们在多次使用mybatis generator重新生成代码时会导致在已有生成的文件上追加生成重复的内容,导致代码错误,故我建议如果你只生成一次代码,以后再不用工具生成可以关闭注释,如果会重复生成就要把注释开关打开。我的配置参数是关闭时间注释:

[code="xml"]
<commentGenerator>
<property name="suppressDate" value="true"/>
</commentGenerator>
[/code]

4 我们可以在生成好的代码上继续添加我们要实现的功能代码,但是在用中文注释代码的时候,我们再用generator重新生成代码,我们已有代码是不会被覆盖和修改的,但是中文注释有可能变成乱码,这是因为我们在工具配置文件上没有全局指定文件编码,只要我们在context的配置区域里面加入如下配置即可:

[code="xml"]
<property name="javaFileEncoding" value="UTF-8"/>
[/code]

5. mybatis generator生成的代码注释比较丑陋,同时也不支持在model代码中自动添加数据库字段注释,我们可以通过修改插件源代码来实现。从官网下载插件

https://github.com/mybatis/generator/tree/master/core/mybatis-generator-core

核心代码,修改/mybatis-generator-core/src/main/java/org/mybatis/generator/internal/DefaultCommentGenerator.java

文件,其中addFieldComment 方法的参数introspectedColumn即包含了数据库字段的相关数据,调用的方法是getRemarks ,怎么修改我就不说了,你懂的。



Jul18

Zip文件数据结构说明

Author: leeon  Click: 9139   Comments: 0 Category: 算法  Tag: zip

zip文件由三部分组成:压缩的文件内容源数据、压缩的目录源数据、目录结束标识结构

1、 压缩的文件内容源数据:

记录着压缩的所有文件的内容信息,其数据组织结构是对于每个文件都由file header 、file data、data descriptor三部分组成。

1)File header:用于标识该文件的开始,结构说明如下:

 

                               Header

Offset

Bytes

Description

0

4

Local file header signature = 0x04034b50 (read as a little-endian number)

文件头标识,值固定(0x04034b50)

4

2

Version needed to extract (minimum)

解压文件所需 pkware最低 版本 

6

2

General purpose bit flag

通用位标记

8

2

Compression method

压缩方法

10

2

File last modification time

文件最后修改时间

12

2

File last modification date

文件最后修改日期

14

4

CRC-32

说明采用的算法。

18

4

Compressed size

压缩后的大小。

22

4

Uncompressed size

非压缩的大小。

26

2

File name length (n)

文件名长度

28

2

Extra field length (m)

扩展区长度

30

n

File name

文件名

30+n

m

Extra field

扩展区

 

2)file data :相应压缩文件的源数据。

 

3)data descriptor:用于标识该文件压缩结束,该结构只有在相应的header中通用标记字段的第3位设为1时才会出现,紧接在压缩文件源数据后。这个数据描述符只用在不能对输出的 ZIP 文件进行检索时使用。例如:在一个不能检索的驱动器(如:磁带机上)上的 ZIP 文件中。如果是磁盘上的ZIP文件一般没有这个数据描述符。

结构说明如下

   Data descriptor

Offset

Bytes

Description[18]

 0

4

Local file header signature = 0x08074b50

本地header标记

 4

4

CRC-32

CRC-32

 8

4

Compressed size

压缩后大小

 12

4

Uncompressed size

非压缩的大小

 

2、 压缩的目录源数据

对于待压缩的目录而言,每一个子目录对应一个压缩目录源数据,记录该目录的描述信息。压缩包中所有目录源数据连续存储在整个归档包的最后,这样便于向包中追加新的文件。

结构说明如下

Central directory file header

 

Offset

Bytes

Description[18]

 0

4

Central directory file header signature =0x02014b50

核心目录文件header标识=(0x02014b50)

 4

2

Version made by

压缩所用的pkware版本

 6

2

Version needed to extract (minimum)

解压所需pkware的最低版本

 8

2

General purpose bit flag

通用位标记

10

2

Compression method

压缩方法

12

2

File last modification time

文件最后修改时间

14

2

File last modification date

文件最后修改日期

16

4

CRC-32

CRC-32算法

20

4

Compressed size

压缩后大小

24

4

Uncompressed size

未压缩的大小

28

2

File name length (n)

文件名长度

30

2

Extra field length (m)

扩展域长度

32

2

File comment length (k)

文件注释长度

34

2

Disk number where file starts

文件开始位置的磁盘编号

36

2

Internal file attributes

内部文件属性

38

4

External file attributes

外部文件属性

42

4

Relative offset of local file header. This is the number of bytes between the start of the first disk on which the file occurs, and the start of the local file header. This allows software reading the central directory to locate the position of the file inside the ZIP file.

本地文件header的相对位移。

46

n

File name

目录文件名

46+n

m

Extra field

扩展域

46+n+m

k

File comment

文件注释内容

 

3、 目录结束标识结构

目录结束标识存在于整个归档包的结尾,用于标记压缩的目录数据的结束。

结构说明如下

End of central directory record

Offset

Bytes

Description[18]

 0

4

End of central directory signature =0x06054b50

核心目录结束标记(0x06054b50)

 4

2

Number of this disk

当前磁盘编号

 6

2

Disk where central directory starts

核心目录开始位置的磁盘编号

 8

2

Number of central directory records on this disk

该磁盘上所记录的核心目录数量

10

2

Total number of central directory records

核心目录结构总数

12

4

Size of central directory (bytes)

核心目录的大小

16

4

Offset of start of central directory, relative to start of archive

核心目录开始位置相对于archive开始的位移

20

2

Comment length (n)

注释长度

22

n

Comment

注释内容

分类

标签

归档

最新评论

Abyss在00:04:28评论了
Linux中ramdisk,tmpfs,ramfs的介绍与性能测试
shallwe99在10:21:17评论了
【原创】如何在微信小程序开发中正确的使用vant ui组件
默一在09:04:53评论了
Berkeley DB 由浅入深【转自架构师杨建】
Memory在14:09:22评论了
【原创】最佳PHP框架选择(phalcon,yaf,laravel,thinkphp,yii)
leo在17:57:04评论了
shell中使用while循环ssh的注意事项

我看过的书

链接

其他

访问本站种子 本站平均热度:8823 c° 本站链接数:1 个 本站标签数:464 个 本站被评论次数:94 次