2019独角兽企业重金招聘Python工程师标准>>>
重构系统的套路系列:
- 重构系统的套路-写有组织的代码
- 重构系统的套路-提高并发能力
- 重构系统的套路-微服务化
本篇说下重构系统的套路中的,明确重构的目的。
我们进行系统重构会抱着不同的目的,比如为了系统稳定性,为了系统中某些功能负载能力更强,为了系统更便于维护,或是为了系统更便于持续集成提升RD和QA的人效。
不同的重构目的会有不同的重构方式和不同的执行标准。
比如为了系统稳定性的重构,我们更需要关心的是系统稳定性指标,我们需要在整个服务链路上进行梳理,梳理出核心链路,核心链路的耗时控制及QPS,如果不能在整个链路上下游达成统一,往往会造成一些未知且不可控的问题。
比如如果某个服务进行稳定性重构,独断专行的设置了对下游服务的耗时,上线后,整个服务虽然稳定性提升,但是下游服务由于不合理的超时时间造成数据落库失败,在整个链路上看其实这个请求也是失败的,造成的结果就是一个服务的可用性和稳定性上来了,但是整个链路的可用性却降低了,贸然全量这样一个重构,必然产生一个非常大的事故。 如果直接把一个500ms设置成100ms,结果没有在意到这个500ms是一个数据上报功能,其实对核心业务不影响,但是因为降低了400ms造成上报数据系统超时,最终统计数据有误,造成金融结算金额错误,所以一个小小的修改超时时间造成了一个如此大的问题。
如果重构的目的是为了负载能力,比如为了半年整个订单量翻一倍,QPS提升三倍,我们首先需要对现有系统进行压测,发现系统瓶颈,通过完善的监控系统进行耗时稳定代码和逻辑评估,针对性优化。 同时需要对整个重构服务所依赖的缓存,持久化存储,redis,mq等系统容量进行评估,系统中线程池进行评估,而所有的评估都是建立在对对应中间件所服务目的来实现的。
比如我们用redis集群做幂等服务,因为多服务同步之间通过定时任务触发,定时任务触发后可能因为大数据量造成请求挤压,高峰期挤压处理在2~5h不等,所以这个redis的key的超时时间需要覆盖到5h,梳理了程序代码逻辑就ok了吗?
结果服务上线后,整个代码逻辑跑起来没问题,可以高峰期间发现异常日志和错误数据统计不停上升,结果发现是没有正确评估系统QPS,同时没有梳理好redis的key大小,5h的超时时间使得整个key的存储瞬间达到20G+,而某个集群容量可能已经满了,而DBA来不及进行集群扩容,集群自身触发缓存清除策略,大量的key删除造成集群数据的rebalance,造成网络抖动,结果造成高峰期间集群可用性降低,当redis集群可用性降低到一定阈值之后,系统逻辑降级读db,造成了雪崩,整个数据库集群也被压倒,造成了一个重大事故。
上面这个虽然是我自己在系统梳理过程中意淫出来的场景,但我不得不再我进行类似系统重构之前,在代码逻辑角度,功能业务角度,缓存集群,mq集群,DB集群等角度考虑,我这次重构可能造成的问题,只有我们在系统重构之间能够想的比黑天鹅来的更快我们才能对系统做更多的保护,当然这一切不能交给QA同学,需要有经验的架构师有全局的视野和掌控。
如果系统重构的目的在于可维护性,和上面两点的区别在于,周期不可操之过急。 我们需要在整个业务角度去理解系统,同时对未来系统所承接的业务有所评估,这样我们才能设计出一个面向未来的系统。 编写可维护的代码和可维护的系统其实非常的难,微服务的流行和DDD的流行其实也很难根本上解决这个问题,终极的解决方案还是在将RD培养成领域专家,在领域角度去抽象和理解业务,编写领域驱动的代码,而不是简单的认为分层和多模块的搞就可以了。
如果系统重构的目标在于持续集成和发布,提升RD和QA的人效,则需要在工程和流程及文化三个角度去做。 工程上提供便于管理的git系统,全链路压测系统,集成测试环境,多泳道支撑,一键资源申请,完善的上线发版流程及快速回滚方案,QA同学具备正常的http抓包分析能力,测试代码编写能力,基本linux的shell编写能力。 RD编写测试用例,完善技术文档,覆盖功能修改点,配合qa同学观察耗时,连接建立,磁盘IO,机器load,cpu等多指标。 控制发版时间和发版粒度,指定安全发版策略等。
基于以上四点不同的重构需求,我们采取的方案和执行的角度完全不同,系统变大了之后,稳定第一。