有句古话,叫做好架构是迭代出来的,不是设计出来的。那么是不是说在系统设计之初的的架构不重要呢?我觉得要从两个方面解读
1. 之初的架构设计当然重要,一个产品在5年后还能运行良好并且仍然可以需求迭代,就得益于优秀的架构
2. 优秀的架构设计,也需要架构师在需求迭代过程中进行架构迭代和重构。
在产品漫长的生命周期中,不定会有啥需求,把架构推倒重来的的情况也可能发生。但是架构上遇到的问题,比较普遍的还是如下一些情况:
1. 最初的架构设计的服务边界不清晰、系统耦合度太高。架构师没时间跟进每一个业务需求,所以在需求迭代时,开发人员开发时就怎么方便怎么来,自己怎么理解的怎么来。
2. 架构师缺位,没有进行有效的架构优化和系统拆分,或者架构师给开发人员的自由度太高,导致架构失控
3. 架构师的话语权或者把控力不足,在遇到紧急需求时,一般以满足业务目标为第一优先级,就在架构上进行了妥协或者推迟重构,结果欠债越来越多
4. 架构文档不更新。新项目开发时,可能架构文档还比较完善,随着每次的需求迭代,架构的变更逻辑散落在各需求的系分文档中,甚至只剩下口口相传的传说了。
在这些情况下,产品存活的越久,问题就越严重。听之任之,最终变成一坨烂系统:
1. 应用耦合严重.各应用职责不清晰,什么垂直业务拆分,领域边界全不存在了,微服务越来越臃肿,部分应用层微服务承载了几乎所有的业务流程。
2. 业务扩展性差,业务流程case by case,有稍许变更就需要对原流程大动干戈才能支撑,牵一发动全身。
3. 系统扩展性差,无论是业务系统还行DB,承接业务快速发展越来越吃力
4. 跨层依赖甚至循环依赖,调用链路越来越长,响应越来越慢
5. 代码越来越难以维护,大量的硬编码,坏味道,修改起来战战兢兢
6. 遇到大的需求迭代,甚至要测试完所有的主要流程才敢上线。
最后越走越远,系统变的没人敢改,没人愿意改,没人改的动,剩下的就是烧香拜佛求平安。
在这里,根据我实际做过的一次架构重构,和大家一起讨论。
1. 确定系统当前的问题
要做架构重构,一定是当前系统出现问题。那么首先要明确的,就是当前系统出现了什么问题,重构要解决什么问题?这是我们做重构的基础,也是我们要向各方明确的重构的必要性。
在架构重构之前,要明确我们当前的问题是什么?问题是否是真正的从业务需求出发?还是架构师仅仅想炫技?是否有其他优化方式?比如多增加几台机器能否解决?仅对某部分业务流程优化下是否能够解决?如果不做架构重构,系统最终会出现什么问题?
所以,当前系统是否存在必须要架构重构才能解决的问题,是我们做重构的首要出发点,也是争取领导和开发团队支持所必须明确的理由。
从我的实践来说,重构前主要存在的如下问题:
a. 应用层耦合严重,会员业务和营销业务相互依赖,大量的if-else判断,业务逻辑繁杂零碎,逐渐没人改的动,没人愿意改。某个需求迭代,导致其他流程线上出现问题。万幸的是发现及时进行了订单阻断,否则导致的损失在千万级。
b. 基础领域层边界不清晰,开发团队对各系统的职责逐渐模糊。
c. 部分业务流程流量巨大,占用了40%的资源。该业务流程长期无迭代需求,并且系统稳定性要求高,系统耦合严重导致与其他业务流程相互掣肘。
d. 多需求协作开发时,经常出现版本冲突,甚至影响了上线版本的稳定性。
2. 确定当前架构是什么
既然要做重构,就必须要了解当前的架构是什么。架构师切忌自信爆棚,对当前系统架构一知半解时直接上手,做到一半,才发现对原架构并不十分熟悉,或者不理解原设计思路是为了实现特殊的目的,最终把自己和团队都置于两难的境地。
建议对原架构文档进行学习和了解,对主要的业务路径进行梳理,和开发团队沟通,对代码进行review等。
3. 了解当前业务的发展趋势,未来的规划和主营方向
重构的最终目的是为了满足业务需求,重构的复杂度也不亚于构建一个产品,了解业务规划,有助于我们圈定重构的目标和边界,以及重构的优先级等。业务发展趋势一方面是自己对业务的理解,更重要的要和业务部门沟通,确定当前业务部门的业务目标是什么?当前的痛点是什么?以及业务部门的发展规划是什么,未来会选择哪些方向作为突破点?产品形态会不会发生变化?等等。
4. 明确架构重构的目标和边界
怎么才算完成了重构?完成的标准是靠主观的判断还是可量化的数据?比如重构后,性能提升了20%?开发效能提升了20%?线上问题减少了20%?如何验证是否达到了上述目标?重构的目标不明确或者仅仅依靠主观的判断,那么重构是否完成也就没有标准。从实际操作来说,重构的目标不同,那么重构或者优化的方法也就不同。
从我的实践来说,重构就是要解决上述提到的问题,即主要解决系统耦合和系统稳定性的问题。落实到具体数字上,就是因版本冲突导致的上线问题降至0;主业务流程需求迭代效能提升20%,测试效率提升25%;线上服务器资源节省10%;某业务流程系统稳定性提高,问题降至0。同时需要支撑业务部门最近的业务规划等。
同时也要确认架构的边界,比如系统现在欠的技术债要不要还?哪些还哪些不还?对新引入的技术栈是否玩的转?更细化一点,比如代码是否重构?哪些业务流程要大动干戈?是否对日志有了新规范?等等
5. 获取支持
在架构重构的过程中,会来自多个方向的压力,领导控成本,业务部门要求不影响现有业务发展,开发部门支撑日常的CURD已是疲于奔命。而架构重构本身,对于重构负责人也不是一件特别出彩的事情。新产品的研发,完成新项目的构建,成果大家都看得见,并且积累了从0到1的架构经验,甚至还可以满足下自己炫技的小私心。而重构基本无法对原架构思路进行整体改动,并且是给线上系统做变更,其复杂度更大,限制条件更多。
如何解决这个问题呢,建议是设置重构的里程碑,重构的成果可以逐步体现,同时向各方同步重构的成果,得到各方的认可的同时也可以要求各方增强支持。缓解架构负责人的压力同时也提升了开发团队的成就感。
6. 明确架构重构方案和架构的演进方向
架构重构和新产品架构类似,领域驱动设计现在提的比较多,个人也比较认可。具体的架构方案和现系统的架构、问题息息相关,读者可以自行考虑自己的系统。
从我的实践来看,我面临的主要是系统耦合度导致的问题,其主要解决方法就是
a. 拆分微服务,主要是从业务的角度做垂直拆分
b. 把业务流程较稳定,流量较大,同时业务逻辑又相对独立的流程,从微服务中抽取出来,由单体应用支撑或者链路更短的微服务支撑。
c. 把复用度较高的功能、子流程从应用层中抽取出来并封装,做成基础微服务向各应用层提供能力
d.明确各微服务的职责,同时合并部分职责雷同的微服务
7. 是否需要对线上数据处理
如果涉及到数据模型的变更,或者需要从单表变更从分库分表,则系统重构复杂度又上了一个台阶。我本次并未涉及到数据库模型的变更,一方面是因为数据库性能整体比较牛X,一方面是是新产品上线时就对数据规模做了充分预估,在需求迭代过程中,对数据模型的把控还算到位。
如果你需要从单表变更为分库分表,则线上数据支撑方案会是另外一个话题了,本文章就不再展开了。
8. 架构重构逐步落地的步骤和排期
经过架构方案的调研,编写,评审等,完成了架构方案。但是难点其实还在后面,就是如何落地。
上面已经提到过了设置里程碑,重构效果逐步提现,在实际的落地过程中,会发现这其实也是迫不得已的选择,因为业务部门、开发团队都不会允许一次性投入足够的工作量去把全部重构做完。这也是完全可以理解的。
那么逐步落地的过程中,其实有几个落地的方法
1. 先解决最痛点的问题,让重构尽快见到最明显的效果
2. 需要拆分的微服务,架构方案已规划好怎么拆分了,但是在实际的拆分过程会比较谨慎和漫长,那么对应的新需求过来,可以用新定义的微服务支撑,原功能逐步拆分到新的微服务
3. 各微服务的职责先明确,并且给开发团队讲明白。需要合并的微服务,可先合并,这部分可能涉及的业务流程变更较少
4. 可复用功能的抽取,这部分就需要比较谨慎,稍有不慎,就影响到全局。可小步快跑,逐步迭代,并充分验证去做。
同时需要注意上线时的灰度发布等。
具体的排期,可能会时间比较长,和各方一起制定合理的排期,并跟踪实时的重构进度,并对发现的问题及时复盘。总之先体现部分成果,增强各方包括自己的信心。
9. 重构的质量
其实包括重构的目标验证和代码质量。
目标上述已经提到是明确的,可量化的,从实际的工时、线上跟踪等可以验证,同时线下的压测、代码核查等必不可少。
10. 文档
架构文档,数据模型,主业务流程等等系统架构文档,一定要留存,并且注意在需求迭代过程中更新。并且最好团队内统一开发工具,如数据模型设计工具,UML工具等
11.其他问题
在大环境下,其实有时候工作不仅仅是技术问题,也是利益问题、领导风格问题、甚至在有的公司还有站队问题。面对这些问题,重构负责人要迎难而上,这同时也非常考察架构师的沟通能力。总之要和各方坦诚交流,了解各方关注点,调整目标和优先级,同时和各方共担目标和风险。架构师不要把自己所把控不了的问题扛在自己身上,更不要闷在自己心里。总之,非技术问题是非常正常和常见的,架构师必须面对。
以上,简单说了下架构重构的方法和过程,具体的操作,还需要在实际的过程中进行实践,实践出真知,同时遇到问题也不要气馁,相信自己可以攻克。