升级
一次失败升级后的反思
最近两周因为一个升级搞的精疲力竭,一共熬了四次通宵。睡了一天,总算把觉补回来了。
不得不说这次升级非常失败,为了从哪跌倒从哪爬起,为了以后不再这么悲催,我总结下我收获的经验教训,希望对那些和我们处于同一水平线的项目有些许借鉴意义。
预则立,不预则废
准备不充分是我们这次犯得最严重的问题,从开发到测试再到运维。虽然为了这次升级我们已经忙了几个月,但是在升级这件事上还是过于乐观了,或者说不重视。
先说开发,低估了工作的难度和复杂性(这应该算是程序猿这个物种的通病吧),一而再再而三的出现任务延迟。这次升级主要内容是对原来用C#写的系统用Java重写,所以从编码的角度来说没什么难度,只是时间问题,但可能就是因为“没难度”导致重视不够,最后上线的前一天还发现了好几个bug,开发测试关键时刻总是在做救火的事
另外,上线准备的时候,低估了一些工作所花的时间,导致上线时大分部时间花在了数据迁移上,当出现问题的时候发现留给自己的时间已经不多了。
讨论、讨论、然后就没有然后了
其实准备开始的足够早,考虑到一次性升级的东西太多,也计划分步骤来上线。有会议记录,有文档,有邮件……,但是结果却没有按计划的时间点执行。 至于原因很多,可能真的是太忙了吧。
环境问题
测试环境:
1、 首先测试环境非常混乱,组件那么多,都部署在一台机器上,相互影响的可能性谁也说不清楚;
2、 一开始一直没有提供一个完整的集成测试环境让客户端集成测试,导致集成测试不充分。
3、 测试环境和现网环境差距比较大(部署结构、数据量、硬件…)导致性能测试的结果没有100%说服力,升级过程中发现好几次测试环境性能ok,上线后却出现了问题。
现网环境:
1、 几台机器的环境不一致(部署路径不一样,mysql版本等),直接的影响就是出现问题的时候,变量太多了,由不得大家不乱猜,结果就是越猜越乱,时间都浪费在了验证各种变量和配置上面了。最严重的是导致修改了一天的验证性工作都白做了,严重打击了大家自信心,大伙本来就累得够呛还感觉在做无用功,效率极其低下。
2、 硬件的问题。当最后定位发现时硬盘有问题的时候,运维同事自己都说“这机器不适合做服务器”,我只能“呵呵”,熬了两个通宵,眼皮都抬不起来了…
3、 现网优化不足,比如mysql就发现查询缓存没有开启。
应对问题的准备不够
一开始过于乐观,风险评估不足。没有做好应对问题的打算,比如提前准备好profile工具,开启mysql的慢查询日志……尤其是第一次升级失败后,第二次仍然过于乐观,拍脑袋认为问题已经解决了,最后导致第二次升级基本白做。
每次升级都应该抱着最坏的打算。
补充:导致升级反复的另外一个重要原因就是测试环境验证的问题。尤其是第一次升级失败后,没有仔细分析现网的数据,没有把现网的包拉下来做对比验证,就妄下断论。后面几次验证出现反复的修改回退代码,手动打一大堆包,测试环境的变量总是不停的变(一会连这个库一会连那个库,一会这个配置一会那个配置),最后我们自己都弄不清哪个包对应哪个版本,因为时间紧中间做的一大堆验证测试都没有做记录,后果就是像无头苍蝇一样,做了很多无用功。中间暴露了两个问题:1.缺乏数据收集(包括日志记录不详细,验证没有做记录等);2.分析问题不足(有日志也没有仔细分析)。第一点相对来说容易解决,第二点我想除了技术能力,经验非常重要。
技术问题
首先需要自我反思的是引进的一些新技术没有能够研究透彻,导致上线后性能很不理想。随着系统负载压力越来越大,不像之前网上随便找找复制粘贴拿来用就可以了,不光知其然还要知其所以然。
从这次暴露出来的问题,我觉得我们可以朝以下几点努力,其中有的我们已经尝试在做了:
1、自动化部署。我们现在的部署方式太原始了,完全依赖手动操作,有多少台tomcat测试就要准备好多少个war包,而且依赖测试手动的去一个个修改配置文件,效率太低。当然一口吃不了个胖子,可以先逐步的脚本化。
2、 配置管理。这次升级过程中发现配置太多,而且写在一个本地文件里,开发、测试和上线,版本库就那一个文件,相互影响,上线时候依赖测试手动修改,太容易出错了。要想实现自动化部署,首先要解决的就是配置问题。
3、自动化测试。和自动化部署目的是一样的减少人力的投入,减少失误。解放人才能提高生产力,现在我们的测试手段还是比较落后的,还是依赖测试一个个去手动执行用例,像上线后验证这种工作完全可以脚本自动化完成。
4、服务降级。系统应该具备一定的降级能力,这样出现问题的时候,可以通过拒绝一些出现问题的服务来保证其他服务正常,这样可以边验证已经上线的功能一边修复问题。
5、平滑升级。完全的平滑升级不太可能,但做一些系统升级的时候如何在尽可能不影响现有服务的情况下完成升级是很值得思考的。其实我们这次升级最欠考虑的一个地方就是把后端存储结构也一起改了,这就导致新系统和老系统完全不能兼容,上线和回退的成本都比较高,非常浪费时间。最后我们也是调整了方案,让后端存储保持一致,先从nginx拉一点流量到新部署的tomcat上,发现没问题,再逐步的迁移,等所有web应用服务器升级完了,下次再考虑升级后端的存储结构。
团队发展
我们现在这个项目正处于一个发展阶段,而运维已经先行动起来了,慢慢规范起来了,现网各种权限只有运维有,现网的操作完全依赖运维一个人操作,这是必然的趋势,时代不同了,不再是当年一两个人时开发测试运维一人全包了,但是在自动化部署、持续集成等等这些都还没来得及跟上的这个阶段,升级的瓶颈往往就出现在运维这块了。这次升级发现一个无赖的情形:部署时或出现问题时一大堆人围着运维,有的干瞪眼,有的不停说着运维不熟悉的业务方面的术语,效率非常低。当下敏捷和DevOps非常流行,不知道是否可以解决这个问题?