# 架构学习书摘总结（五）架构实战

> 作者：zning（https://ning.ae） · 发布：2019/09/15 09:24 上午 (UTC+8) · 原文：https://zning.me/15600074562241.html

最近阅读了一本架构方面的入门图书叫《从零开始学架构：照着做，你也能成为架构师》，部分内容比较不错，先做书摘总结，以便加深印象与未来回顾学习。

本文是该书第五部分，是书中第十六至二十章，主要介绍消息队列设计、互联网架构演进及模板、架构重构和开源系统等架构实际案例内容。

连续阅读，请点击如下链接：

* [架构学习书摘总结（一）概念和基础部分](./15511868502157.html)

* [架构学习书摘总结（二）高性能架构模式](./15517030839592.html)

* [架构学习书摘总结（三）高可用架构模式](./15521364926344.html)

* [架构学习书摘总结（四）可扩展架构模式](./15599222898499.html)

* [架构学习书摘总结（五）架构实战](./15600074562241.html)

    
## 第十六章 消息队列设计实战

1. 需求：

    1. 用户发微博，通过审核子系统、统计子系统、广告子系统、消息子系统等，系统间通过接口调用，每通知一个新系统，微博子系统就要涉及接口进行测试，效率很低，问题定位很麻烦。还有等级子系统给VIP用户发放奖励、通知客服子系统安排专属服务人员……开发人员不胜其烦。
    2. 根因在于架构上各业务子系统强耦合，而消息队列正好可以完成子系统的解耦。经过一分析二讨论三开会四汇报五审批等一系列操作后，消息队列系统立项。

2. 设计流程：

    1. 识别复杂度：对架构师来说是一项挑战，如果经验不足，那么只能采取“排查法”，从不同角度逐一进行分析。对于此项目具体分析过程如下：

        1. **这个消息队列是否需要高性能：**关注每秒数据，即TPS和QPS。再考虑系统的读写并不是完全平均的，设计的目标应该以峰值来计算。峰值一般取平均值的3倍。例如，一天平均每秒写入消息为115条，每秒读取消息数是1150条，则消息对类系统的TPS是345，QPS是3450。另外由于现在基数较低，因此系统的设计目标按照峰值的四倍来计算，即TPS为1380，QPS为13800。TPS为1380并不高，但QPS为13800已经比较高了，因此高性能读取是复杂度之一，但这个高性能要求相比Kafka等系统来说也不是很高。
        2. **这个消息队列是否需要高可用：**消息队列需要高可用性，包括消息写入、消息存储、消息读取都需要保证高可用性。
        3. **这个消息队列是否需要高可扩展性：**消息队列的功能很明确，基本无需扩展，因此可扩展性不是这个消息队列的复杂度关键。

        综合分析下来，消息队列的复杂性主要体现在几个方面：高性能消息读取、高可用消息写入、高可用消息存储、高可用消息读取。

    2. 设计备选方案：采用开源Kafka、集群+MySQL存储、集群+自研存储方案。

    3. 评估和选择备选方案
        
        | 质量属性 | 引入Kafka | MySQL存储 | 自研存储 |
        | --- | --- | --- | --- |
        | 性能 | 高 | 中 | 高 |
        | 复杂度 | 低，基本开箱可用 | 中，MySQL存储和复制，方案只需要开发服务器集群就可以 | 高，自研存储方案复杂度很高 |
        | 硬件成本 | 低 | 高，一个分区就4台机器 | 低，和Kafka一样 |
        | 可运维性 | 低，无法融入现有的运维体系，且运维团队无Scala经验 | 高，可以融入现有运维体系，MySQL运维很成熟 | 高，可以融入现有运维体系，并且只需要维护服务器即可，无需维护MySQL |
        | 可靠性 | 高，程序开源方案 | 高，MySQL存储很成熟 | 低，自研存储系统可靠性在最初阶段难以保证 |
        | 人力投入 | 低，开箱即用 | 中，只需要开发服务器集群 | 高，需要开发服务器集群和存储系统  |

        最终根据讨论与架构师决策，选择了备选方案2。

    4. 细化方案：在备选方案的基础上进一步细化。

## 第十七章 互联网架构演进

1. 什么样的策略才是真正有效的技术发展策略这个问题让人困惑关键的原因在于不管是潮流派（紧跟技术潮流）、保守派（新技术抱有戒备心，稳定压倒一切），还是跟分派（跟着竞争对手的步子走），都是站在技术本身的角度来考虑问题的，正所谓“不识庐山真面目，只缘身在此山中”。因此，要想看到“庐山真面目”，只有跳出技术的范畴，从一个更广更高的角度——企业的业务发展来考虑这个问题。
2. 企业的发展，归根结底就是业务的发展，而影响一个企业的发展主要有3个因素：市场、技术、管理。在这个铁三角当中，业务处于三角形的中心，毫不夸张的说，市场、技术、管理都是为了支撑企业业务的发展。
3. 我们可以简单地将企业的业务分为两类：产品类和服务类。
4. 对于产品类服务，**技术创新推动业务发展**。对于服务类服务，**业务发展推动技术发展**。两类不同关系的原因在于用户选择服务的根本驱动力与选择产品的不同。用户选择一个产品的根本驱动力是其“功能”，而用户选择一个服务的根本驱动力却为“规模”。
5. 当“规模”成为业务的决定因素后，服务模式的创新就成为业务发展的核心驱动力，而产品只是为了完成服务而提供给用户使用的一个载体。
6. 服务类的业务发展路径：提出一种创新的服务模式→吸引了一批用户→业务开始发展→吸引了更多用户→服务模式不断完善和创新→吸引越来越多的用户。
7. 即使是产品类业务，在技术创新开创了一个新的业务后，后续的业务发展也会反向推动技术的发展。
8. 对于架构师来说，判断业务当前和接下来一段时间的主要复杂度是什么是非常关键的。架构师具体应该按照基于业务发展阶段的标准进行判断，这也是为什么架构师必须具备业务理解能力的原因。
9. 互联网业务具有“规模决定一切”的相同点。
10. 互联网业务发展一般分为几个时期：初创期、快速发展期、竞争期、成熟期。不同时期的差别主要体现在两个方面：复杂性、用户规模。
11. 互联网发展的第一个主要方向是“业务越来越复杂”。

    **初创期**业务重点在于创新，只有随着越来越多的用户的使用，通过快速迭代试错、用户的反馈等手段，不断地在实践中去完善，去继续创新。

    **发展期**主要是将原来不完善的业务逐渐完善，因此会有越来越多的新功能不断地加入系统中。对于绝大部分技术团队来说，这个阶段技术的核心工作是快速地实现各种需求，只有这样才能满足业务发展的需要。

    **架构期**进行架构调整，架构期可以用的手段很多，但归根结底可以总结为一个字“拆”，功能、数据库、服务器等什么地方都可以拆。

    **竞争期**对技术的要求更上一层楼的“快”了，新业务的创新给技术带来的典型压力就是新的系统会更多，同时，原有的系统也会拆得越来越多。两者合力的一个典型后果就是系统数量在原来的基础上又增加了很多。而系统越来越多到了一个临界点后就产生到了质变，即系统数量的量变带来了技术工作的质变。主要有重复造轮子、系统交互一团麻。这个时期技术工作的主要解决手段有平台化（存储平台化、数据库平台化、缓存平台化）、服务化（消息队列、服务框架等）。

    **成熟期**进行逐项优化。

1. 互联网发展的第二个主要方向是“用户量越来越”大。主要影响体现在：性能要求越来越高、可用性要求越来越高。

    性能：再简单的查询，再高的硬件配置，单台MySQL机器支撑的TPS和QPS最高也就是万级，低的可能是几千，高的也不过几万。分布式将会带来复杂度的大幅度上升。以MySQL为例，分布式MySQL要考虑分库分表、读写分离、复制、同步等很多问题。
    
    可用性：除了口碑，可用性对收入的影响也会随着用户量增大而增大。1万用户宕机1小时，可能才损失了几千元，100万用户宕机10分钟，损失可能就是几十万元了。

## 第十八章 互联网架构模板

![2019-9-15](media/15600074562241/2019-9-15.jpg)

上图基本涵盖互联网技术公司的大部分技术点，不同的公司只是在具体的技术实现上稍有差异，但不会跳出这个框架的范畴。

1. 存储层技术
    1. SQL

        SQL即我们通常所说的关系型数据(库)。随着互联网业务的发展，性能要求越来越高，必然面对一个问题：将数据拆分到多个数据库实例才能满足业务的性能需求（其实Oracle也一样，只是时间早晚的问题）。数据库拆分满足了性能的要求，但带来了复杂度的问题：数据如何拆分、数据如何组合。所以互联网公司流行的做法是业务发展到一定阶段后，就会将这部分功能独立成中间件，例如淘宝的TDDL。再后期会导致新的复杂度问题：数据库资源使用率不高，比较浪费以及各SQL集群分开维护，投入的维护成本越来越高。因此，实力雄厚的大公司此时一般都会在SQL集群上构建SQL存储平台，以对业务透明的形式提供资源分配、数据备份、迁移、容灾、读写分离、分库分表等一系列服务。例如，淘宝的UMP(Unified MySQL Platform)系统。
    2. NoSQL

        NoSQL不是No SQL，而是Not Only SQL，即NoSQL是SQL的补充。首先NoSQL在数据结构上与传统的SQL的不同，例如典型的Memcache的key-value结构、Redis的复杂数据结构、MongoDB的文档数据结构；其次，NoSQL无一例外地都会将性能作为自己的一大卖点。

        NoSQL的这两个特点很好地弥补了关系数据库的不足，因此在互联网行业NoSQL的应用基本上是基础要求。
        
        由于NoSQL方案一般自己本身就提供集群功能，因此NoSQL在刚才是应用时很方便，不像SQL分库分表那么复杂。而NoSQL发展到一定规模后，通常都会在NoSQL集群的基础之上再实现统一存储平台。同意存储平台主要实现资源动态按需动态分配、资源自动化管理、故障自动化处理等几个功能。当然要发展到这个阶段，一般也是大公司才会这么做，简单来说就是如果只有几十台NoSQL服务器，那么做存储平台的收益不大；但如果有几千台NoSQL服务器，那么NoSQL存储平台就能够产生很大的收益。

    3. 小文件存储
 
        除了关系型的业务数据，互联网行业还有很多用于展示的数据。这些数据具有数据量小一般在1M以下、数据量巨大、访问量巨大的典型特点。Facebook 2013年就达到每天上传3.5亿张照片，访问量超过10亿的规模。和SQL和NoSQL不同的是，小文件存储不一定需要公司或者业务规模很大，基本上认为业务在起步阶段就可以考虑做小文件统一存储。得益于开源与大数据，开源方案基础上封装一个小文件存储平台不太难。例如HBASE、Hadoop、Hypertable、FastDFS等都可以作为小文件存储的底层平台，只需要在这些开源方案上再包装一下基本上就可以用了。
 
    4. 大文件存储

        互联网行业的大文件主要分为两类：一类是业务上的大数据，例如YouTube的视频、电影；一类是海量的日志数据，例如各种访问日志、操作日志、用户轨迹日志等。大文件没有小文件那么多，但每个文件都很大。这块开源方案也很成熟了，所以大数据存储和处理可以选择Hadoop、HBASE、Storm、Hive等。

2. 开发层技术
    1. 开发框架

        互联网公司都会指定一个大的技术方向，然后使用统一的开发框架。例如，Java相关的开发框架SSH、SpringMVC、SpringCloud、Play，Ruby的Ruby on Rails，PHP的ThinkPHP，Python的Django等等。使用统一的开发框架能够解决上面提到的各种问题，大大提升组织和团队的开发效率。
        
        对于框架的选择，有一个总的原则：**优选成熟的框架，避免盲目追逐新技术**。首先，成熟的框架资料文档齐备；其次，成熟的框架受众更广，招聘时更容易招到合适的人才；最后，成熟的框架更加稳定，不会出现大的变动，适合长期发展。

    2. Web服务器

        开发框架只是负责完成业务功能的开发，真正能够运行起来，给用户提供服务，还需要服务器配合。选择一个服务器主要和开发语言相关，例如Java有Tomcat、JBoss、Resin等，PHP/Python的用Nginx，当然最保险的就是用Apache了，什么语言都支持。有人要担心Apache性能之类的问题，其实不用过早担心这个，等到业务真的发展到Apache撑不住的时候再考虑切换也不迟，那时候你有的是钱，有的是人，有的是时间。

    1. 容器

        传统的虚拟化技术是虚拟机，解决了跨平台的问题，但由于虚拟机太庞大，启动慢，运行时太占资源，在互联网行业并没有大规模地应用；而Docker的容器技术，虽然没有跨平台，但启动快，几乎不占资源，推出后立刻就火起来了。不要以为Docker只是一个虚拟化或容器技术，它将在很大程度上改变目前的技术形势：

        1. 运维方式会发生革命性的变化：Docker启动快，几乎不占资源，随时启动停止，基于Docker打造自动化运维、智能化运维将成为主流方式。
        2. 设计模式会发生本质上的变化：启动一个新的容器实例代价如此低，将鼓励设计思路朝“微服务”的方向发展。

        例如，一个传统的网站包括登录注册、页面访问、搜索等功能，没有用容器的情况下，除非有特别大的访问量，否则这些功能开始时都是集成在一个系统里面的；有了容器技术以后，一开始就可以将这些功能按照服务的方式设计，避免后续访问量增大时又要重构系统。

1. 服务层技术

    服务层的主要目标是为了降低系统间相互关联的复杂度。

    1. 配置中心

        配置中心就是集中管理各个系统的配置。将配置中心做成通用的系统有如下好处：
        
        1. 集中配置多个系统，操作效率高。
        2. 所有配置都在一个集中的地方，检查方便，协作效率高。
        3. 配置中心可以实现程序化的规则检查，避免常见的错误。
        4. 配置中心相当于备份了系统的配置，当某些情况下需要搭建新的环境时，能够快速搭建环境和恢复业务。

        配置中心通过“系统标示+host+port”来标示唯一一个系统运行实例是常见的设计方法。

    1. 服务中心

       服务中心未来解决跨系统依赖的配置和调度问题。其实现一般来说有两种方式：服务名字系统和服务总线系统。
       
       服务名字系统（Service Name System），类似于DNS，其是为了将Service名称解析为“host+port+接口名称”，但是和DNS一样，真正发起请求的还是请求方。
       
       服务总线系统（Service Bus System），类似于计算机总线，其为了直接又总线系统完成调用，服务请求方不需要直接和服务提供方交互。
       
       两者简单对比如下：
       
       
        |   | 服务总线系统 | 服务名字系统 |
        | --- | --- | --- |
        | 复杂度 | 设计更加复杂，要同时完成配置和调度功能，且本身高性能和高可用的设计也更加复杂。 | 设计简单，基本类似一个服务配置中心，如果要做调度，需要独立的SDK包。 |
        | 可用性 | 可用性的关键，它故障后所有业务间的访问都鼓掌，影响较大，但因为服务总线主要做调度，可以部署两套或多套并行系统。 | 仅仅保存配置，屌用还是由服务请求方发起，可用性要求没那么高，即使故障，各系统也可以使用本地缓存配置继续完成调用。 |
        | 灵活性 | 控制所有的调度和配置，可以做得非常灵活。 | 仅仅有配置，即使提供独立的SDK支持调度，灵活性也要差一点，毕竟SDK只能获取静态的配置信息。 |
        | 实时性 | 系统完成实际的调度，可以做到非常实时，例如某个服务及机器故障后立刻剔除故障节点。 | 提供调度的SDK包，也需要定时更新配置，不能每次请求都去获取一下最新的配置，实时性一般，这个问题和DNS类似。 |
        | 可维护性 | 服务总线系统的修改和升级只需要自己完成即可。 | 修改和升级大部分情况下要修改SDK包（例如，调度算法变更），修改SDK包要求所有系统应用新SDK包才能生效。 |
        | 多语言支持 | 服务总线系统支持通用的HTTP和TCP协议，和语言无关。 | 服务名字系统提供的SDK包需要适配多个语言，这个工作量也不小。  |
 

    2. 消息队列

        消息队列系统基本功能的实现比较简单，但要做到高性能、高可用、消息时序性、消息事务性则比较难。

1. 网络层技术
    1. 负载均衡

        负载均衡就是将请求均衡的分配到多个系统上。其实现方式很多，可大可小，可以软件实现，也可以硬件实现。
        
        DNS是最简单也是最常见的负载均衡方式，一般用来实现地理级别的均衡。DNS负载均衡的有点事通用、成本低，但缺点也明显：DNS缓存时间比较长；DNS不能感知后端服务器的状态，只能根据配置策略进行负载均衡，无法做到更加灵活的负载均衡策略。所以对于时延和故障敏感的业务，有一些公司自己实现了HTTP-DNS的功能，即使用HTTP协议实现一个私有的DNS系统，这样的方案与通用DNS优缺点正好相反。
        
        Nginx&LVS&F5用于同一地点内及其级别的负载均衡，其中Nginx是软件的7层负载均衡，LVS是内核的4层负载均衡，F5是硬件做4层负载均衡。
        
        软件和硬件的区别就在于性能，硬件远远高于软件，Nginx的性能是万级，一般的Linux服务器上装个Nginx大概能到5万/秒；LVS的性能是十万级，没有具体测试过，据说可以达到80万/秒；F5性能是百万级，从200万/秒-800万/秒都有。
        
        4层和7层的区别在于协议和灵活性。Nginx支持HTTP、E-mail等协议，而LVS和F5是4层负载均衡，和协议无关，几乎所有应用都可以做，例如聊天、数据库等。

    2. CDN

        CDN是为了解决用户忘了访问时的”最后一公里“效应，即将内容缓存在离用户最近的地方，用户访问的是缓存的内容，而不是站点实时内容。CDN经过多年的发展，已经变成了一个很庞大的体系：分布式存储、全局负载均衡、网络重定向、流量控制等都属于CDN的范畴。

    3. 多机房

        多机房设计最核心的因素就是如何处理时延带来的影响。常见策略有：
        
        **同城多机房：**可搭建私有高速网络，基本做到与同机房一样的效果。对业务影响较小，但投入较大，而且遇到地震水灾等严重自然灾害也是有很大风险。
        
        **跨城多机房：**机房间通过网络进行数据复制，但由于跨城网络时延问题业务上需要做一定的妥协和兼容，不需要数据的实时强一致性，保证最终一致性即可。这种方式实现简单，但和业务有很强的相关性，微博可以这样做，支付宝就不能这样做。
        
        **跨国多机房：**同跨城多机房，只是地理分布更远、时延更大。所以一般仅用于备份和服务本国用户。

    4. 多中心

        多中心要求每个中心都同时对外提供服务，且业务能够自动在多中心之间切换，故障后不需要人工干预或很少干预就能自动恢复。
        
        多中心设计的关键就在于”数据一致性“和”数据事务性“如何保证，但这两个难点都和业务紧密相关，不存在通用的解决放哪，需要基于业务的特性进行详细的分析和设计。正因为多中心设计的复杂性，不一定所有业务都能实现多中心，目前国内的银行、支付宝这类系统就没有完全实现多中心。不然也不会出现挖掘机一铲子下去，支付宝中断4小时的故障。

2. 用户层技术
    1. 用户管理

        第一个目标：SSO，单点登录，又叫统一登录。单点登录的技术实现手段较多，例如cookie、token等，最有名的开源方案为CAS。
        
        第二个目标：授权登录。现在最流行的授权登录就是OAuth 2.0协议，基本上已经成为事实上的标准，如果要做开放平台，则最好用这个协议，私有协议漏洞多，第三方介入也麻烦。
        
        用户管理面临的主要问题是用户数巨大，一般至少千万级，但实现起来并不难，主要是因为不同用户之间没有关联。

    2. 消息推送

        消息推送根据不同的途经，分为短信、邮件、站内信、App推送。App目前主要分为iOS和Android推送，iOS系统比较规范和封闭，基本上只能使用苹果的APNS了；但Android在国外用GCM和APNS差别不大，但在国内GCM不能用，另外各个厂商都有自己定制的Android，消息推送实现也不完全一样。通常情况下，对于中小公司，如果不涉及敏感数据，则Android系统上推荐使用第三方推送服务，因为这些第三方是专业做推送服务的，消息到达率是有一定保证的。
        
        如果涉及敏感数据，则需要自己实现消息推送，这时就有一定的技术挑战了。消息推送主要包含3个功能：设备管理（唯一标识、注册、注销）、连接管理和消息管理，技术上面临的主要挑战有：海量设备和用户管理、连接保活、消息管理。

    3. 存储云与图片云

        通常的实现都是”CDN+小文件存储“。由于图片业务的复杂性，普通的文件基本上提供存储和访问功能就够了，但图片涉及的业务可能包括裁剪、压缩、美化、审核、水印等处理，因此通常情况下图片云会拆分为独立的系统对用户提供服务。

3. 业务层技术

    业务层面对的主要技术挑战是复杂性，而不管什么业务难题，用上”拆“问题一般都迎刃而解。究其原因，复杂性的一个主要原因就是系统越来越庞大，业务越来越多，降低复杂性最好的方式就是“拆”，化整为零、分而治之，将整体复杂性分散到多个子业务或子系统里面去。
    
    而子系统数量过多，则需要“合”。按照“高内聚，低耦合”的原则，将职责关联比较强的子系统合成一个虚拟业务域，然后通过网关对外统一呈现，类似于设计模式中的Facade模式。

4. 平台技术

    1. 运维平台

        运维平台核心的职责分为四大块：**配置**（资源管理：机器、IP、虚拟机）、**部署**（将系统发布到线上：包、灰度发布、回滚）、**监控**（收集系统上线运行后的相关数据并进行监控以便及时发现问题）、**应急**（系统出故障后的处理：停止程序、下线故障机器、切换IP）。
        
        运维平台的核心设计要素：**标准化、平台化、自动化、可视化**。

        **标准化：**需要制定运维标准，规范配置管理、部署流程、监控指标、应急能力等，各系统按照运维标准来实现，避免不同的系统不同的处理方式。标准化是运维平台的基础，没有标准化就没有运维平台。
        
        **平台化：**在运维标准化的基础上，将运维的相关操作都集成到运维平台中，通过运维平台来完成运维工作。通过平台可将运维标准固化到平台中，且可以同简单方便的操作，可以复用支撑几百上千个业务系统。
        
        **自动化：**将重复操作固化，由系统自动完成。类似还有监控。
        
        **可视化：**提升数据查看效率，原理与汽车仪表盘类似。可直观地看到数据的相关属性，能够将数据的含义展示出来，能够将关联数据整合一起展示。

    2. 测试平台

        核心职责是测试，包括单元测试、集成测试、接口测试、性能测试等。测试平台的核心目的是提升测试效率，从而提升产品质量，其设计关键就是自动化。为达到自动化，测试平台包括用例管理、资源管理、任务管理、数据管理等。

    3. 数据平台

        核心职责包括数据管理、数据分析和数据应用。其中数据管理包括数据采集、数据存储、数据访问和数据安全四个核心职责，是数据平台的基础。数据分析包括数据统计、数据挖掘、机器学习、深度学习等几个细分领域。数据应用就广泛了，既包括在线业务，也包括利息按业务。例如推荐、广告等属于在线应用，报表、欺诈简称、异常检测等属于离线应用。

    4. 管理平台

        核心职责是权限管理，无论业务系统（例如淘宝网）、中间件系统（例如消息队列Kafka），还是平台系统（例如运维平台）都需要进行管理。权限管理主要分为两部分：身份认证、权限控制。

## 第十九章 架构重构

1. 系统架构是不断演化的，少部分架构演化可能需要推倒重来进行重写，但绝大部分的架构演化都是通过架构重构来实现的。架构重构对架构师的要求更高，主要体现在：

    1. 业务已经上线，不能停下来
    2. 关联方众多，牵一发动全身
    3. 旧架构的约束

    因此架构重构对架构师的综合能力要求非常高，业务上要求架构师能够说服产品经理暂缓甚至暂停业务来进行架构重构；团队上需要架构师能够与其他团队达成一致的架构重构计划和步骤；技术上需要架构师给出让技术团队认可的架构重构方案。

1. 有的放矢：期望通过架构重构来解决所有问题当然是不现实的，所以架构师的首要任务是从一大堆纷繁复杂的问题中识别出真正要通过架构重构来解决的问题，集中力量快速解决，而不是想着通过架构重构来解决所有的问题。尤其是对于刚接手一个新系统的架构师或技术主管来说，一定要控制住“新官上任三把火”的冲动，避免摊大饼式或运动式的重构和优化。架构师需要透过问题表象看到问题本质，找出真正需要通过架构重构解决的核心问题。

2. 合纵连横：

    1. 合纵：要想真正推动一个重构项目启动，需要花费大量的精力进行游说和沟通。一般技术人员谈到架构重构时，就会搬出一大堆技术术语，但如果和非技术人员这样沟通，效果如同鸡同鸭讲，没有技术背景的人员很难理解，甚至有可能担心我们是在忽悠人。所以在沟通协调时，将技术语言转换为通俗语言，以事实说话，以数据说话，是沟通的关键。例如某系统不用直接说可用性是几个9，而是整理线上故障的次数、每次影响的时长，影响的用户，客服的反馈意见等，然后再拿其他系统的数据进行对比，无论产品人员、项目人员，还是运营人员，明显就看出系统的可用性有问题了。
    2. 连横：有重构需要和其他相关或配合的系统的沟通协调。由于大家都是做技术的，所以这里沟通协调容易写，但是也有阻力，主要有“这对我有什么好处”和“这部分我这边现在不急”。前者会被误认为“不顾大局”，但其实首先这种拔高一般都比较虚，无法明确，不同人的理解不一样，无法达成共识；其次是如果对公司和部门有利，但对某个小组没用甚至不利，那么可能是因为目前的方案不够好，还可以考虑另外的方案。推动的有效策略是“换位思考、合作双赢、关注长期”，即站在对方角度思考，重构对他有什么好处，能够帮他解决什么问题，带来什么收益。当然有的时候有些情况需要协调更高层级的管理者才能推动，平级推动是比较难的。

3. 运筹帷幄：架构师在识别系统关键的复杂度问题后，还需要识别为了解决这个问题，需要做哪些准备事项，或者还要先解决哪些问题。其实就是**分段实施**，将要解决的问题根据优先级、重要性、实施难度等划分为不同的阶段，每个阶段聚焦于一个整体的目标，集中精力和资源解决一类问题。

    制定分段实施策略有如下经验：

    1. 划分优先级：将明显且有比较紧急的事项优先落地，解决目前遇到的主要问题。
    2. 问题分类：将问题按照性质分类，每个阶段集中解决一类问题。
    3. 先易后难：这点与很多人的直觉不太一样，有的人认为应该先攻克最难的问题，所谓的“擒贼先擒王”，解决最难的问题后其他问题就不在话下。这看起来很美好，但实际上不可行。采取先易后难的策略，能够很大程度上避免“先易后难”策略的问题。

4. 文武双全：项目管理+技术能力

    真正的架构师，当然必须具备一定的项目经理技能，但更重要的还是技术能力，道理很简单：再好的饼，最后实现不了，都是空谈！“项目管理能力”是“文”的能力，“技术能力”是“武”的能力，架构师必须文武双全才能解决问题。
    
    我们牢记架构设计的目的：**架构设计的主要目的是为了解决系统的复杂性。**
    
    某些系统关键问题是“不合理的耦合带来的复杂性”：将特定业务的数据和所有业务的公共数据耦合在一起，数据正确性难以保证，而且每次修改都是“牵一发动全身”，效率很高，所以重构的目标就是将“不合理的耦合”进行拆分。
    
    而某些系统主要的问题就是有一个全局单点，一旦这个单点故障，就会导致所有业务全部不可用。所以我们重构的目标就是解决“全局唯一单点”的可用性问题。

## 第二十章 开源系统

1. 开源项目虽然节省了大量的人力和时间，但带来的踩坑（宕机、丢数据等）问题也不少。
2. 架构师需要更加聪明的去选择和使用开源项目，即不要重复造轮子，但要找到合适的轮子。
3. 选-如何选择一个开源项目：聚焦是否满足业务、聚焦是否成熟（可以看版本号、使用的公司数量、社区活跃度判断）、聚焦运维能力（可以从开源方案日志是否齐全、开源方案是否有命令行管理控制台等维护工具能看到系统运行时的情况、开源方案是否有故障检测和恢复的能力例如告警、倒换等）。
4. 用-如何使用开源方案：
    1. 深入研究，仔细测试。可通过如下几个方面进行研究和测试：
        1. 通读开源项目的设计文档或白皮书，了解其设计原理。
        2. 核对没给配置项的作用和影响，识别出关键配置项。
        3. 进行多种场景的性能测试。
        4. 进行压力测试，连续跑几天，观察CPU、内存、磁盘I/O等指标波动。
        5. 进行故障测试，kill、断电、拔网线、重启100次以上、倒换等。
    2. 小心应用，灰度发布：不管研究多深入、测试多仔细、自信心多爆棚，时刻对线上环境和风险要有敬畏之心，小心使得万年船。经验就是先在非核心的业务上应用，然后有经验后再慢慢扩展。
    3. 做好应急，以防万一：运气不好可能遇到一个之前全世界的使用者都从来没遇到的bug。
5. 改-如何基于开源项目做二次开发
    1. 保持纯洁，加以包装：建议不要改动原系统，而是要开发辅助系统：监控、告警、负载均衡、管理等。
    2. 发明你要的轮子：软件领域和硬件领域最大的不同就是前者没有绝对的工业标准，大家都很尽兴，想怎么玩就怎么玩。除此以外，开源项目未来能够大规模应用，考虑的是通用性的处理方案，而不同的业务其实差异较大，通用方案并不一定完美适合具体的某个业务。所以，如果你有钱有人有时间，投入人力去重复发明完美符合自己业务特点的轮子也是很好的选择。毕竟，很多财大气粗的公司（BAT们）都是这样做的，否则我们也就没有那么多好用的开源项目了。

## 其他相关摘要
1. 实际中，不同的公司或团队，可能还有一些其他方面的复杂度分析。例如，金融系统可能需要考虑安全性，有的公司会考虑成本等。
2. 通常情况下，成熟的团队不会轻易改变技术栈，反而是新成立的技术团队更加倾向于采用新技术。
3. 架构师的技术储备越丰富，经验越多，备选方案也会更多，从而才能更好地涉及备选方案。
4. 备选方案的选择和很多因素有关，并不单单考虑性能高低、技术是否优越这些纯技术因素。业务的需求特点、运维团队的经验、已有的技术体系、团队人员的技术水平都会影响备选方案的选择。
