一次发布事故总结

系统发布是最没技术含量,但却又是最关键且危险的一步。

到目前为止,自己也已布了大大小小版本不下十次,每次发布还是提心吊胆的。小版本发布还好,出错了很容易定位问题所在,但是发布大版本可就像光脚走在刀刃上一般,稍有不慎,后果不堪设想。

就之前的几次系统发布经历来说,都还算稳定,小版本基本不会出什么问题,大版本虽然也出过一两次问题,最后还是能及时发现了。但是今天这次大版本的发布让我遭遇了滑铁卢。下面来复盘一下今天从打包到发布的一系列过程。


时间:8:40

操作:代码打分支和打包

容易出错点:1.版本号写错;2.编译版本出错(编译成测试环境的 war 包)
具体内容:

 考虑到昨天下午想到有一个点忘记和测试姑娘们说了,所以昨天火急火燎的让测试姑娘们测了下。为了防止再出现 bug ,计划就是在今天早上打包代码的,加之现在新的服务器较之于老测试服务器,性能有显著的提升,在新服务器上打完两个包的时间基本维持在 10min- 。所以在发布当天早上打包的决定并没有什么问题。打完 branch 和 tag 并在服务器上编译好前端代码打好 war 包 总共花了 30min- 。先前在这一步踩过一次坑,就是编译时候没注意,打出了 测试环境的 war 包,现在想想真是被自己蠢笑了。当然也因为这个原因,我写了个能自动判断版本并修改对应参数和部署的 Python 脚本(悲伤的是这个脚本就在今天已经不能继续它的使命了)。


时间:10:20

操作:发布申请表

容易出错点:无

具体内容:
 主要工作就是把本期功能罗列出来。发送给 PM 。


时间:10:30

操作:将发布包放到生产环境并配置好参数

容易出错点:1.参数写错

具体内容:

 每次最担心的就是这一步。因为之前写了一个自动部署的脚本,所以以往都只要执行一下脚本然后再去确认一遍参数改过来没有就可以了。可是,一个脚本是不足以让程序员一劳永逸的(主要是因为我写那个脚本的时候没有考虑太多情况),这次发布配置文件添加了一些东西,是我脚本里面没有写进去的,所以在执行完脚本后,因为配置文件信息和脚本里预编译的参数匹配不上,这次脚本就魂归故里了(有时间还是会想办法让它进化一下)。手工修改配置信息的话,出错率大大增加,所以如果是手工配置的话,基本上我都要检查三遍,第一遍修改后,第二遍发布前,第三遍发布后。所以修改配置信息的时候真的不能手抖,不然你连怎么死的都不知道。今天发布事故其实也算是出在这一步了,加之我对系统框架的整体不够熟悉,所以面对新添加的接口不知道哪个该启用哪个该停用,导致了发布后 h5 的服务直接抛异常了。其实发布之前也向“校长”问过这两个接口怎么处理,只是我没有仔细考虑就发布了(百密一疏哇)。个人感觉这一步完全可以在测试阶段就发现,无奈这一期 h5 和 flex 放到两个环境了,所以不能模拟出生产环境,漏过了这个大 bug 。主要原因还是在自己不够细致,下次发布前对所有接口进行一次验证,并在测试完后就在测试环境模拟一次生产环境发布。(另外还需要加强组员提交代码的警觉性,昨天又有同学把日志 SQL 打印开成 debug 模式了。)


时间:12:00

操作:执行 SQL 脚本

容易出错点:1.脚本遗漏;2.脚本没执行等

具体内容:
 其实这里还应该考虑一点就是 SQL 脚本和发布等顺序问题。今天生产没有发布成功,回滚后,生产的数据已经无法回滚了。所以今天如果是先发布系统然后再执行脚本,这样是可以安全回滚的,唯一的缺点是如果不先执行脚本就发布,发布的时候可能直接抛异常,服务无法启动等问题,会增加问题排查的难度。所以最好的方式还是先在测试环境模拟一下生产环境,可行后再发布。


时间:12:30

操作:启动服务

容易出错点:1.启动时间;2.启动前先查看下日志判断当前有无 job 等在执行中;3.启动前先确定 tomcat 进程已经关闭

具体内容:

 这一步只要不手抖,基本不会出什么问题。


时间:12:35

操作:查看flex 和 h5 服务是否正常

容易出错点:无

具体内容:

 根据 IP 访问,查看功能是否正常。当然,今天 app1 发布后,h5 服务没有起来,后来将 app1 的请求全部转到 app2 上,在 app1 上排查出了问题。

排查过程:

  1. 会不会是打包出错了?

    打包和发布流程都和以前一样,所以问题出现在打包编译阶段的可能性很低,而且将 tag 放到测试环境,是可以起来的,所以证明问题不是出在打包和编译阶段。

  2. 会不会是 tomcat 配置文件的地址或者解压包放错位置?

    看来下 tomcat 到配置文件并没有问题。解压包为止也是正确的。所以并不是这个问题。

  3. 会不会是 h5 相关的代码写错了?

    问了下参与这期开发的同学们,并没有什么业务功能实现代码牛逼到可以让服务瘫痪的。所以基本排除这种可能性。

  4. 那么还会有什么问题?

    或许是因为平时服务启动的时候总会报几个正常的异常,所以这次也就没在意,直到我再次将服务启动的时候,冒出了一个我不曾见过的异常,马上知道这是接口问题。


总结:

  • 这次事故产生的责任在我,这没得说。
  • 在测试完成阶段加入一次生产环境模拟测试(由开发人员自行完成)。
  • 通过这次事故,意识到了对整体框架的把控还是十分欠缺的,现在的状态更像是框架在驾驭我,而不是我在驾驭框架,所以在面对服务端一个整体的时候,完全不像我对前端框架那样游刃有余。所以既然有这么多可以挑战的地方,肯定很有趣,没什么可说的,就是玩。
  • 经验的积累。如果是一名久经沙场的老程序员遇到我今天的问题,估计两分钟就把问题定位出来了。当然如果下次再碰到这种问题,我估计也就两三分钟定位出来吧。所以这就是经验的力量啊。
Comments
Write a Comment