“架构设计三原则”中的演化原则部分系统的架构是不断演化的少部分架构演化可能需要推倒重来进行重写但绝大部分的架构演化都是通过架构重构来实现的。架构重构对架构师的要求更高主要体现在业务已经上线不能停下来架构重构时业务已经上线运行了重构既需要尽量保证业务继续往前发展又要完成架构调整而如果是新设计架构业务还没有上线则即使做砸了对业务也不会有太大影响。关联方众多牵一发动全身架构重构涉及的业务关联方很多不同关联方的资源投入程度、业务发展速度、对架构痛点的敏感度等有很大差异如何尽量减少对关联方的影响或者协调关联方统一行动是一项很大的挑战而如果是新设计架构则在新架构上线前对关联方没有影响。旧架构的约束架构重构需要在旧的架构基础上进行这是一个很强的约束会限制架构师的技术选择范围而如果是新设计架构则架构师的技术选择余地大得多。即使是我们决定推倒到重来完全抛弃旧的架构而去设计新的架构新架构也会受到旧架构的约束和影响因为业务在旧架构上产生的数据是不能推倒重来的新架构必须考虑如何将旧架构产生的数据转换过来。因此架构重构对架构师的综合能力要求非常高业务上要求架构师能够说服产品经理暂缓甚至暂停业务来进行架构重构总之架构重构需要架构师既要说得动老板也要镇得住同事既要技术攻关又要协调资源既要保证业务正常发展又要在指定时间内完成目标……总之就是十八般武艺要样样精通。架构重构第一式有的放矢。通常情况下当系统架构不满足业务的发展时其表现形式是系统不断出现各种问题轻微一点的如系统响应慢、数据错误、某些用户访问失败等严重的可能是宕机、数据库瘫痪、数据丢失等或者系统的开发效率很低。真正开始进行架构重构分析时就会发现自己好像进了一个迷雾森林到处都是问题每个问题都需要解决不知道出路在哪里感觉如果要解决所有这些问题架构重构其实也无能为力。期望通过架构重构来解决所有问题当然是不现实的所以架构师的首要任务是从一大堆纷繁复杂的问题中识别出真正要通过架构重构来解决的问题集中力量快速解决而不是想着通过架构重构来解决所有的问题。否则就会陷入人少事多头绪乱的处境团队累死累活弄个大半年最后发现好像什么都做了但每个问题都依然存在。尤其是对于刚接手一个新系统的架构师或者技术主管来说一定要控制住“新官上任三把火”的冲动避免摊大饼式或者运动式的重构和优化。具体的重构案例1. 后台系统重构解决不合理的耦合 M 系统是一个后台管理系统负责管理所有游戏相关的数据重构的主要原因是因为系统耦合了 P 业务独有的数据和所有业务公用的数据导致可扩展性比较差。其大概架构如下图所示。举一个简单的例子数据库中的某张表一部分字段是所有业务公用的“游戏数据”一部分字段是 P 业务系统“独有的数据”开发时如果要改这张表代码和逻辑都很复杂改起来效率很低。针对 M 系统存在的问题重构目标就是将游戏数据和业务数据拆分解开两者的耦合使得两个系统都能够独立快速发展。重构的方案如下图所示。重构后的效果非常明显重构后的 M 系统和 P 业务后台系统每月上线版本数是重构前的 4 倍2. 游戏接入系统重构解决全局单点的可用性问题S 系统是游戏接入的核心系统一旦 S 系统故障大量游戏玩家就不能登录游戏。而 S 系统并不具备多中心的能力一旦主机房宕机整个 S 系统业务就不可用了。其大概架构如下图所示可以看出数据库主库是全局单点一旦数据库主库不可用两个集群的写业务都不可用了。针对 S 系统存在的问题重构目标就是实现双中心使得任意一个机房都能够提供完整的服务在某个机房故障时另外一个机房能够全部接管所有业务。重构方案如下图所示。重构后系统的可用性从 3 个 9 提升到 4 个 9重构前最夸张的一个月有 4 次较大的线上故障重构后虽然也经历了机房交换机宕机、运营商线路故障、机柜断电等问题但对业务都没有什么大的影响。3.X 系统解决大系统带来的开发效率问题X 系统是创新业务的主系统之前在业务快速尝试和快速发展期间怎么方便怎么操作怎么快速怎么做系统设计并未投入太多精力和时间很多东西都“塞”到同一个系统中导致到了现在已经改不动了。X 系统的问题看起来和 M 系统比较类似都是可扩展性存在问题但其实根本原因不一样M 系统是因为耦合了不同业务的数据导致系统可扩展性不足而 X 系统是因为将业务相关的所有功能都放在同一个系统中导致系统可扩展性不足同时所有功能都在一个系统中也可能导致一个功能出问题整站不可用。比如说某个功能把数据库拖慢了整站所有业务跟着都慢了。针对 X 系统存在的问题重构目标是将各个功能拆分到不同的子系统中降低单个系统的复杂度。重构后的架构如下图所示(仅仅是示例实际架构远比下图复杂)。重构后各个系统之间通过接口交互虽然看似增加了接口的工作量但整体来说各系统的发展和开发速度比原来快了很多系统也相对更加简单也不会出现某个子系统有问题所有业务都有问题。这三个系统重构的方案现在回过头来看感觉是理所当然的但实际上当时做分析和决策时远远没有这么简单。以 M 系统为例当时我们接手后遇到的问题有很多例如数据经常出错。M 系统是单机单机宕机后所有后台操作就不能进行了。性能比较差有的操作耗时好久。界面比较丑操作不人性化。历史上经过几手转接代码比较混乱。业务数据和游戏数据耦合开发效率很低。从这么多问题中识别出重构的目标并不是一目了然的而如果想一下全部解决所有这些问题人力和时间又不够所以架构师需要透过问题表象看到问题本质找出真正需要通过架构重构解决的核心问题从而做到有的放矢既不会耗费大量的人力和时间投入又能够解决核心问题。架构重构第二式合纵连横合纵架构重构是大动作持续时间比较长而且会占用一定的研发资源包括开发和测试因此不可避免地会影响业务功能的开发。因此要想真正推动一个架构重构项目启动需要花费大量的精力进行游说和沟通。注意这里不是指办公室政治而是指要和利益相关方沟通好让大家对于重构能够达成一致共识避免重构过程中不必要的反复和争执。一般的技术人员谈到架构重构时就会搬出一大堆技术术语可扩展性、可用性、性能、耦合、代码很乱……但从过往的实际经验来看如果和非技术人员这样沟通效果如同鸡同鸭讲没有技术背景的人员很难理解甚至有可能担心我们是在忽悠人。连横有的重构还需要和其他相关或者配合的系统的沟通协调。沟通协调其实相对来说要容易一些但也不是说想推动就能推动的主要的阻力来自“这对我有什么好处”和“这部分我这边现在不急”。对于“这对我有什么好处”问题有的人会简单理解为这是自私的表现认为对方不顾大局于是沟通的时候将问题人为拔高。例如“你应该站在部门的角度来考虑这个问题”“这对公司整体利益有帮助”等。这种沟通效果其实很差首先是这种拔高一般都比较虚无法明确不同的人理解也不一样无法达成共识其次是如果对公司和部门有利但对某个小组没用甚至不利那么可能是因为目前的方案不够好还可以考虑另外的方案。架构重构第三式运筹帷幄经过分析和思考我们可能从最初的 100 个问题列表挑选出其中 50 个是需要在架构重构中解决的其中一些是基础能力建设或者准备工作而另外一些就是架构重构的核心工作。最简单的做法是每次从中挑一个解决最终总会把所有的问题都解决。第一个原因是没有区分问题的优先级所有问题都一视同仁没有集中有限资源去解决最重要或者最关键的问题导致最后做了大半年回头一看好像做了很多事情但没取得什么阶段性的成果。第二个原因是没有将问题分类导致相似问题没有统筹考虑方案可能出现反复效率不高。第三个原因是会迫于业务版本的压力专门挑容易做的实施到了稍微难一点的问题的时候就因为复杂度和投入等原因被搁置达不到重构的真正目的。重构的做法其实就是“分段实施”将要解决的问题根据优先级、重要性、实施难度等划分为不同的阶段每个阶段聚焦于一个整体的目标集中精力和资源解决一类问题。这样做有几个好处每个阶段都有明确目标做完之后效果明显团队信心足后续推进更加容易。每个阶段的工作量不会太大可以和业务并行。每个阶段的改动不会太大降低了总体风险。具体如何制定“分段实施”1. 优先级排序 将明显且又比较紧急的事项优先落地解决目前遇到的主要问题。2. 问题分类 将问题按照性质分类每个阶段集中解决一类问题。例如X 系统的第二阶段我们将多个底层系统切换到公司统一的公共组件提升整体可用性。3. 先易后难首先一开始就做最难的部分会发现想要解决这个最难的问题要先解决其他容易的问题。其次最难的问题解决起来耗时都比较长占用资源比较多如果一开始做最难的可能做了一两个月还没有什么进展和成果会影响相关人员对项目的评价和看法也可能影响团队士气。第三刚开始的分析并不一定全面所以一开始对最难的或者最关键的事项的判断可能会出错。采取“先易后难”的策略能够很大程度上避免“先难后易”策略的问题。首先随着项目的推进一些相对简单的问题逐渐解决会发现原来看起来很难的问题已经不那么难了甚至有的问题可能都消失了。其次先易后难能够比较快地看到成果虽然成果可能不大但至少能看到一些成效了对后续的项目推进和提升团队士气有很大好处。第三随着项目的进行原来遗漏的一些点或者分析和判断错误的点会逐渐显示出来及时根据实际情况进行调整能够有效地保证整个重构的效果。4. 循序渐进 按照前 3 个步骤划分了架构重构的实施阶段后就需要评估每个阶段所需要耗费的时间很可能会出现有的阶段耗时可能只要 1 个月而有的却需要 6 个月虽然这可能确实是客观事实但通常情况下按照固定的步骤和节奏更有利于项目推进。上一章: 互联网架构模板下一章: 开源项目如何选择、使用以及二次开发归类: 从0开始学架构