在上篇文章中我们阐述的重点是新版本的插件已经下载到plugins目录后应该如何更新本地正在运行的程序,是整个插件升级实现的后半部分。本篇文章就来讲述软件自动部署(当然,也包括插件升级)的前半部分。
我们必须有这样一点认识,即:我们的程序是运行在用户机器上的,插件更新不是我们手动放进去的,而必须有一种机制使客户端能够检测到需要升级插件了,然后将插件自动下载下来,最后自动进行安装或插件更新。
系统软件自动部署实现的基本架构为:
上图中的组成中,【应用】和【更新服务】部分是运行在客户端的,【数据库】和【文件服务器】是运行在服务端,而【Server (WebServer)】则负责客户端与服务端进行通信,其基本的流程如下:
1> 客户端的【更新服务】采用QTimer::singleShot()定时触发版本检测的逻辑。
2> 版本检测逻辑中采用WebServer请求访问服务端的版本检测服务(通过PHP实现),服务端回去访问【数据库】,去检查比较是否有更高版本的插件/升级包。
3> 检测信息返回给客户端的【更新服务】,当【更新服务】根据返回结果判定存在较新的插件/安装包时,开始访问【文件服务器】执行下载操作,这里可以采用FTP下载,或者其它的某种方式将【文件服务器】上的更新文件下载到本地相应目录内。
4> 最后这一部分是系统软件部署/插件升级最麻烦的地方,客户端的【更新服务】会去判断【应用】模块中是否正在运行作业或者对外提供服务。如果此时【应用】模块没有对外提供服务,则在给出用户提示的情况下可以直接升级或安装;如果此时【应用】模块正在对外提供服务,则需要采用空闲时更新的策略,当对外服务完成之后进行更新。
基本上系统软件自动部署的逻辑架构就如上所示,但在实际代码中要实现还需要考虑一些很重要的问题。
1. 要兼容安装包/升级包的各种文件,下载的文件有exe,dll,zip包等,必须要能够区分出下载文件的后缀名,然后根据不同的后缀,采用不同的安装或升级策略。
2. 要兼容各种平台,Windows、Linux、Mac OS等,不同的平台下安装包的形式有各种各样,例如:windows下有exe、dll、zip等;Linux下有rpm、tar.gz等。
3. 当【应用】模块正在对外提供服务,例如:正在进行网络操作,有打开的端口,在进行插件更新或升级包安装时必须先将原有占用的端口停掉,然后等插件更新完成后重新打开端口恢复以前的任务。这个过程不是很好控制,现在还没有处理这方面问题的经验。
最后,由于客户端要和服务端进行通信,因此必须采用定义相同的数据结构或通信协议,而在这个时候采用的google protobuf则提供了很大的灵活性。它的使用方式不仅简单,而且效率更高(通常和xml进行比较),而且支持很多语言版本,PHP、C++、Java等,强烈建议在以后的项目中涉及到网络通信时采用google protobuf来定义网络协议,它会给你带来意向不到的惊喜。
坚持每天的学习和积累,加油!