部署器开源记 · 第 4 / 4 篇 上一篇 · 参数怎么填进去 合集目录

前面那五步(停服、替换配置、备份、覆盖、安装启动)是「装」的路径。但发版到最后往往不是装,是升级,已经有一套在跑,要换成新版本。这两条路径我做了两套东西,一套制包,一套升级,最后都收回到同一条执行链上。

制包由一个策略驱动,进度权重分三档,SQL 迁移脚本占 5%,模块文件迁移占 10%,打包占 85%。八成以上的时间花在压 zip 上,这个分布不意外,SharpZipLib 压大目录本来就慢。全程可以取消,靠一个取消标志位轮询。

(等价改写,名字换掉了)制包的时候有几样东西不进包:

var excludedNames = new HashSet<string> { "WrapperConfig.xml" };
var excludedExts  = new HashSet<string> { ".log", ".old", ".pdb" };

加上配置模板,进包的就只剩模块文件和 SQL 脚本。这保证了别人拿到包之后,还是要先过一遍参数填写那一步,不用你替他决定这个库名叫什么。

升级没有第二套引擎

升级这块的设计我挺满意,升级包解开以后走的是同一条五步链,没有另写一套执行逻辑。只有一个解压策略负责把 zip 倒进临时版本目录,倒完就交棒,剩下的交给部署链。

临时目录是先清空再解包的,所以同一个包反复跑不会叠加。然后按目录名去匹配模块,临时版本目录里存在这个模块目录,本轮就参与;不存在就跳过。这条让一个升级包可以只包含部分模块,不必是全量。

三条链(部署、制包、升级)的收尾方式是一致的,取消靠轮询一个标志位,进度靠一个事件总线广播,最终状态收敛到三个:成功、失败、取消。这三处统一起来,界面上才不会每个模块一套进度显示。

备份退不回去

这一节我不想夸它。覆盖前确实会备份,但备份目录不带时间戳,每次覆盖上一次的备份。对比一下,同一个策略里的 SQL 脚本归档是带了 yyyyMMdd 的,所以脚本有历史版本,普通文件没有。

还有一个更隐蔽的地方,取不到待备份文件、或者单个文件复制异常的时候,备份这一步照样返回成功,部署链继续往下走。三者叠起来,实际效果是「覆盖完了才发现原来那个文件早就被覆盖了」。

仓库里也没有回滚入口,找不到任何一个方法负责从备份目录恢复。出事只能人去翻备份目录,手动拷回去。

如果你打算拿这个项目改自己的东西,这三处是我会先动手补的:备份目录加时间戳、备份失败就中止、补一个回滚。我不补的原因写在另一组文章里,那是有取舍的:备份做了,却退不回去、那笔代价算在谁头上。

这一组合计四篇,门面在 发版那五步,我为什么没做成命令行,工程结构在 十个工程,依赖只有一个方向,参数怎么填在 参数是怎么填进配置文件的。

本篇是《部署器 · 开源记》第 4 篇,合集在 部署器 · 开源记。