凤凰架构:构建可靠的大型分布式系统

文档信息

  • Release:v1.0.20211226
  • License:Apache 2.0
  • Doc License:CC 4.0
  • Words:399,677
  • Author:IcyFenix(周志明)
  • 发行日期:2021-12-26
  • Star:4,598
  • Follow:2,685
  • Fork:497

这是什么?

这是一部以“如何构建一套可靠的分布式大型软件系统”为叙事主线的开源文档,是一幅帮助开发人员整理现代软件架构各条分支中繁多知识点的技能地图。文章《什么是“凤凰架构”》详细阐述了这部文档的主旨、目标与名字的来由,文章《如何开始》简述了文档每章讨论的主要话题与内容详略分布,供阅前参考。

笔者出于以下目的,撰写这部文档:

  • 笔者从事大型企业级软件的架构研发工作,借此机会,系统性地整理自己的知识,查缺补漏,将它们都融入既有的知识框架之中。
  • 笔者正式出版的前七本计算机技术书籍都不是与自己本职工作直接相关,能按照自己的兴趣去写作,还能获得不菲的经济报酬是一件很快乐的事情;而撰写一部工作中能直接使用的、能随时更新、与人交流的在线文档,同样也是一件很实用、很有价值的事情。
  • 笔者认为技术人员成长有一“捷径”,学技术不仅要去看、去读、去想、去用,更要去说、去写。将自己“认为掌握了的”知识叙述出来,能够说得有条理清晰,讲得理直气壮;能够让他人听得明白,释去心中疑惑;能够把自己的观点交予别人的审视,乃至质疑,在此过程之中,会挖掘出很多潜藏在“已知”背后的“未知”。未有知而不行者,知而不行,只是未知。

除文档部分外,笔者同时还建立了若干配套的代码工程,这是针对不同架构、技术方案(如单体架构、微服务、服务网格、无服务架构,等等)的演示程序。它们既是文档中所述知识的实践示例,亦可作为实际项目新创建时的可参考引用的基础代码。

如何使用?

根据“使用”的所指含义的不同,笔者列举以下几种情况:

在线阅读

本文档在线阅读地址为:https://icyfenix.cn
网站由 GitHub Pages 提供网站存储空间;由 Travis-CI 提供的持续集成服务实时把 Git 仓库的 Markdown 文档编译同步至网站,并推送至 CDN,提供国内的访问加速。

离线阅读

  • 部署离线站点:文档基于 Vuepress 构建,如你希望在企业内部搭建文档站点,请使用如下命令:

    # 克隆获取源码
    $ git clone https://github.com/fenixsoft/awesome-fenix.git && cd awesome-fenix
     
    # 安装工程依赖
    $ npm install
     
    # 运行网站,地址默认为http://localhost:8080
    $ npm run dev
  • 生成PDF文件:工程源码中已带有基于 vuepress-plugin-export 改造(针对本文档定制过)的PDF导出插件,如你希望生成全文 PDF 文件,请在已进行上一步工程克隆和依赖安装的前提下使用如下命令:

    # 编译PDF,结果将输出在网站根目录
    $ npm run export

    PDF 全文编译时间较长,在笔者机器上约耗时25分钟,在 Travis-CI 上约需要约8分钟,可以从这里下载更新时由 Travis-CI 自动编译的PDF。PDF 中文字体采用阿里巴巴普惠字体渲染,此字体被允许免费使用与传播。

二次演绎、传播和发行

本文档中所有的内容,如引用其他资料,均在文档中明确列出资料来源,一切权利归属原作者。除此以外的所有内容,包括但不限于文字、图片、表格,等等,均属笔者原创,这些原创内容,笔者声明以知识共享署名 4.0 发行,只要遵循许可协议条款中署名、非商业性使用、相同方式共享的条件,你可以在任何地方、以任何形式、向任何人使用、修改、演绎、传播本文档中任何部分的内容。详细可见本文档的“协议”一节。

运行技术演示工程

笔者专门在探索起步中的“技术演示工程”详细介绍了配套工程的使用方法,如果你对构建运行环境也有所疑问,在附录中的“环境依赖”部分也已包括了详细的环境搭建步骤。此外,这些配套工程也均有使用 Travis-CI 提供的持续集成服务,自动输出到 Docker 镜像库,如果你只关心运行效果,或只想了解部分运维方面的知识,可以直接运行 Docker 镜像而无需关心代码部分。你可以通过下面所列的地址,查看到本文档所有工程代码和在线演示的地址:

文档工程

前端工程

后端工程

协议

本作品代码部分采用 Apache 2.0协议 进行许可。遵循许可的前提下,你可以自由地对代码进行修改,再发布,可以将代码用作商业用途。但要求你:

  • 署名:在原有代码和衍生代码中,保留原作者署名及代码来源信息。
  • 保留许可证:在原有代码和衍生代码中,保留Apache 2.0协议文件。

本作品文档部分采用 知识共享署名 4.0 国际许可协议 进行许可。遵循许可的前提下,你可以自由地共享,包括在任何媒介上以任何形式复制、发行本作品,亦可以自由地演绎、修改、转换或以本作品为基础进行二次创作。但要求你:

  • 署名:应在使用本文档的全部或部分内容时候,注明原作者及来源信息。
  • 非商业性使用:不得用于商业出版或其他任何带有商业性质的行为。如需商业使用,请联系作者。
  • 相同方式共享的条件:在本文档基础上演绎、修改的作品,应当继续以知识共享署名 4.0国际许可协议进行许可。

目录

数据统计:列入目录文章 101 篇,实际文章总数 107 篇(含目录外文章),合计总字数 399,677 字,最后更新日期 2021-12-26。

  1. 目录
  2. 前言
    • 2.1 关于作者
    • 2.2 关于纸质书
    • 2.3 什么是“凤凰架构”
  3. 探索起步
    • 3.1 阅读指引
      • 3.1.1 更新日志
      • 3.1.2 如何开始
    • 3.2 技术演示工程
      • 3.2.1 前端工程
      • 3.2.2 单体架构:Spring Boot
      • 3.2.3 微服务:Spring Cloud
      • 3.2.4 微服务:Kubernetes
      • 3.2.5 服务网格:Istio
      • 3.2.6 无服务:AWS Lambda
  4. 演进中的架构
    • 4.1 服务架构演进史
      • 4.1.1 原始分布式时代
      • 4.1.2 单体系统时代
      • 4.1.3 SOA 时代
      • 4.1.4 微服务时代
      • 4.1.5 后微服务时代
      • 4.1.6 无服务时代
  5. 架构师的视角
    • 5.1 访问远程服务
      • 5.1.1 远程服务调用
      • 5.1.2 REST 设计风格
    • 5.2 事务处理
      • 5.2.1 本地事务
      • 5.2.2 全局事务
      • 5.2.3 共享事务
      • 5.2.4 分布式事务
    • 5.3 透明多级分流系统
      • 5.3.1 客户端缓存
      • 5.3.2 域名解析
      • 5.3.3 传输链路
      • 5.3.4 内容分发网络
      • 5.3.5 负载均衡
      • 5.3.6 服务端缓存
    • 5.4 架构安全性
      • 5.4.1 认证
      • 5.4.2 授权
      • 5.4.3 凭证
      • 5.4.4 保密
      • 5.4.5 传输
      • 5.4.6 验证
  6. 分布式的基石
    • 6.1 分布式共识算法
      • 6.1.1 Paxos
      • 6.1.2 Multi Paxos
      • 6.1.3 Gossip 协议
    • 6.2 从类库到服务
      • 6.2.1 服务发现
      • 6.2.2 网关路由
      • 6.2.3 客户端负载均衡
    • 6.3 流量治理
      • 6.3.1 服务容错
      • 6.3.2 流量控制
    • 6.4 可靠通讯
      • 6.4.1 零信任网络
      • 6.4.2 服务安全
    • 6.5 可观测性
      • 6.5.1 事件日志
      • 6.5.2 链路追踪
      • 6.5.3 聚合度量
  7. 不可变基础设施
    • 7.1 从微服务到云原生
    • 7.2 虚拟化容器
      • 7.2.1 容器的崛起
      • 7.2.2 以容器构建系统
      • 7.2.3 以应用为中心的封装
    • 7.3 容器间网络
      • 7.3.1 Linux 网络虚拟化
      • 7.3.2 容器网络与生态
    • 7.4 持久化存储
      • 7.4.1 Kubernetes 存储设计
      • 7.4.2 容器存储与生态
    • 7.5 资源与调度
    • 7.6 服务网格
      • 7.6.1 透明通信的涅槃
      • 7.6.2 服务网格与生态
  8. 技术方法论
    • 8.1 向微服务迈进
      • 8.1.1 目的:微服务的驱动力
      • 8.1.2 前提:微服务需要的条件
      • 8.1.3 边界:微服务的粒度
      • 8.1.4 治理:理解系统复杂性
  9. 随笔文章
    • 9.1 2020年
      • 9.1.1 Graal VM
        • 9.1.1.1 新一代即时编译器
        • 9.1.1.2 向原生迈进
        • 9.1.1.3 没有虚拟机的 Java
        • 9.1.1.4 Spring over Graal
      • 9.1.2 QCon2020 主题演讲:云原生时代,Java 的危与机
    • 9.2 2021年
      • 9.2.1 OpenJDK with CLion 懒人包
      • 9.2.2 程序员之路
      • 9.2.3 Fenix-CLI:交互式云原生客户端
      • 9.2.4 ArchSummit2021主题演讲:从软件的历史看架构的未来
  10. 附录
    • 10.1 部署环境
      • 10.1.1 部署 Docker CE 容器环境
      • 10.1.2 部署 Kubernetes 集群
        • 10.1.2.1 使用 Kubeadm 部署
        • 10.1.2.2 使用 Rancher 部署
        • 10.1.2.3 使用 Minikube 部署
    • 10.2 部署 Istio
    • 10.3 部署 Elastic Stack
    • 10.4 部署 Prometheus

关于作者

周志明

Ph.D、Full Stack Programmer、Computer Book Writer、Technical Evangelist、Cloud Native Architect、Most Valuable Professional、HLLVM/PLDI Enthusiast

程序员

兼职一些管理与研究工作的程序员,工作中主要从事大型企业级软件的架构与研发;业余里对计算机科学相关的多个领域都有持续跟进。

研究员

理学博士,曾担任远光软件研究院院长,澳门科大-远光人工智能联合实验室主任,研究方向为机器学习自动化特征选择。

计算机技术作家

出版过八部计算机技术书籍,撰写过两部开源文档,口碑和销量均得到业内认可。其中五本书在豆瓣上获得了 9.0 分及以上的评价,“深入理解 Java 虚拟机”系列重印超过 45 次,销量逾 40 万册。

  • 2021 年 《凤凰架构:构建可靠的大型分布式系统》(豆瓣 9.1)
  • 2020 年 《软件架构探索:The Fenix Project》 (开源文档)
  • 2019 年 《深入理解 Java 虚拟机:JVM 高级特性与最佳实践(第三版)》(豆瓣 9.5)
  • 2018 年 《智慧的疆界:从图灵机到人工智能》(豆瓣 9.1)
  • 2016 年 《深入理解 Java 虚拟机:JVM 高级特性与最佳实践(第二版)》(豆瓣 9.0)
  • 2015 年 《Java 虚拟机规范(Java SE 8 中文版)》(官方授权翻译,豆瓣 8.2)
  • 2014 年 《Java 虚拟机规范(Java SE 7 中文版)》(官方授权翻译,豆瓣 9.0)
  • 2013 年 《深入理解 OSGi:Equinox 原理、应用与最佳实践》(豆瓣 7.7)
  • 2011 年 《深入理解 Java 虚拟机:JVM 高级特性与最佳实践(第一版)》(豆瓣 8.6)
  • 2011 年 《Java 虚拟机规范(Java SE 7 中文版)》 (开源文档)

技术布道师

开源技术的积极倡导者和推动者,国内主流云计算厂商的最有价值技术专家,媒体撰稿人,会议讲师。

  • 阿里云最有价值技术专家(MVP)
  • 腾讯云最有价值技术专家(TVP)
  • 华为云最有价值技术专家(MVP)
  • IBM DeveloperWorks 撰稿人、InfoQ.CN 专栏撰稿人
  • 极客时间布道师、华章 25 周年公益课程讲师、QCon/ArchSummit 全球软件开发大会明星讲师

招聘&内推

对大型软件架构、云原生、实时大数据、企业级软件研发感兴趣的同学,欢迎投简历至:felix.zhouzhiming[at]huawei[dot]com。
团队气氛、水平都很好,对标范围华为18-22级,正编非OD。

关于纸质书

《凤凰架构:构建可靠的大型分布式系统》

衷心感谢在本书撰写过程中,各位读者在本站的建议、意见、讨论、勘误指正与鼓励支持。

如果本书对您有帮助,到豆瓣或者GitHub上给予点赞、评价是对作者最好的支持。

什么是“Phoenix”这个词东方人不常用,但在西方的软件工程读物——尤其是关于 Agile、DevOps 话题的作品中时常出现。软件工程小说《The Phoenix Project》讲述了徘徊在死亡边缘的 Phoenix 项目在精益方法下浴火重生的故事;马丁·福勒(Martin Fowler)对《Continuous Delivery》的诠释里,曾多次提到“Phoenix Server”(取其能够“涅槃重生”之意)与“Snowflake Server”(取其“世界上没有相同的两片雪花”之意)的优劣比对。也许是东西方的文化的差异,尽管有“失败是成功之母”这样的谚语,但我们东方人的骨子里更注重的还是一次把事做对做好,尽量别出乱子;而西方人则要“更看得开”一些,把出错看做正常甚至是必须的发展过程,只要出了问题能够兜底使其重回正轨便好。

在软件工程里,任何产品的研发,只要时间尺度足够长,人就总会疏忽犯错,代码就总会携有缺陷,电脑就总会宕机崩溃,网络就总会堵塞中断……如果一项工程需要大量的人员,共同去研发某个大规模的软件产品,并使其分布在网络中大量的服务器节点中同时运行,随着项目规模的增大、运作时间变长,其必然会受到墨菲定律的无情打击。

墨菲定律(Murphy's Law)

Anything that can go wrong will go wrong. 如果事情可能出错就总会出错。 —— Nevil Maskelyne,1908

为了得到高质量的软件产品,我们是应该把精力更多地集中在提升其中每一个人员、过程、产出物的能力和质量上,还是该把更多精力放在整体流程和架构上?

笔者先给这个问题一个“和稀泥”式的回答:这两者都重要。前者重术,后者重道;前者更多与编码能力相关,后者更多与软件架构相关;前者主要由开发者个体水平决定,后者主要由技术决策者水平决定;

然而,笔者也必须强调此问题的另外一面:这两者的理解路径和抽象程度是不一样的。如何学习一项具体的语言、框架、工具,譬如 Java、Spring、Vue.js……都是相对具象的,不论其蕴含的内容多少,复杂程度高低,它至少能看得见摸得着。而如何学习某一种风格的架构方法,譬如单体、微服务、服务网格、无服务、云原生……则是相对抽象的,谈论它们可能要面临着“一百个人眼中有一百个哈姆雷特”的困境。谈这方面的话题,若要言之有物,就不能是单纯的经验陈述。笔者想来,回到这些架构根本的出发点和问题上,真正去使用这些不同风格的架构方法来实现某些需求,解决某些问题,然后在实践中观察它们的异同优劣,会是一种很好的,也许是最好的讲述方式。笔者想说一下这些架构,而且还想说得透彻明白,这需要代码与文字的配合,于是便有了这个项目。

可靠的系统

让我们再来思考一个问题,构建一个大规模但依然可靠的软件系统,是否是可行的?

这个问题令人听起来的第一感觉也许会有点荒谬:废话。如果这个事情从理论上来说就是根本不可能的话,那我们这些软件开发从业人员现在还在瞎忙活些什么?但你再仔细想想,前面才提到的“墨菲定律”和在“大规模”这个前提下必然会遇到的各种不靠谱的人员、代码、硬件、网络等因素,从中能得出的一个听起来颇为符合逻辑直觉的推论:如果一项工作要经过多个“不靠谱”的过程相互协作来完成,其中的误差应会不断地累积叠加,导致最终结果必然不能收敛稳定才对。

这个问题也并非杞人忧天庸人自扰式的瞎操心,计算机之父冯·诺依曼(John von Neumann)在 1940 年代末期,曾经花费了大约两年时间,研究这个问题并且得出了一门理论《自复制自动机》(Theory of Self-Reproducing Automata),这个理论以机器应该如何从基本的部件中构造出与自身相同的另一台机器引出,其目的并不是想单纯地模拟或者理解生物体的自我复制,也并不是简单想制造自我复制的计算机,他的最终目的就是想回答一个理论问题:如何用一些不可靠的部件来构造出一个可靠的系统。

当时自复制机的艺术表示(图片来自维基百科)

自复制机恰好就是一个最好的用不可靠部件构造的可靠的系统例子。这里,“不可靠部件”可以理解为构成生命的大量细胞、甚至是分子。由于热力学扰动、生物复制差错等因素干扰,这些分子本身并不可靠。但是生命系统之所以可靠的本质,恰是因为它可以使用不可靠的部件来完成遗传迭代。这其中的关键点便是承认细胞等这些零部件可能会出错,某个具体的零部件可能会崩溃消亡,但在存续生命的微生态系统中一定会有其后代的出现,重新代替该零部件的作用,以维持系统的整体稳定。在这个微生态里,每一个部件都可以看作一只不死鸟(Phoenix),它会老迈,而之后又能涅槃重生。

架构的演进

软件架构风格从大型机(Mainframe),到原始分布式(Distributed),到大型单体(Monolithic),到面向服务(Service-Oriented),到微服务(Microservices),到服务网格(Service Mesh),到无服务(Serverless)……技术架构上确实呈现出“从大到小”的发展趋势。当近年来微服务兴起以后,涌现出各类文章去总结、赞美微服务带来的种种好处,诸如简化部署、逻辑拆分更清晰、便于技术异构、易于伸缩拓展应对更高的性能等等,这些当然都是重要优点和动力。可是,如果不拘泥于特定系统或特定某个问题,以更宏观的角度来看,前面所列这种种好处却都只能算是“锦上添花”、是属于让系统“活得更好”的动因,肯定比不上系统如何“确保生存”的需求来得关键、本质。笔者看来,架构演变最重要的驱动力,或者说这种“从大到小”趋势的最根本的驱动力,始终都是为了方便某个服务能够顺利地“死去”与“重生”而设计的,个体服务的生死更迭,是关系到整个系统能否可靠续存的关键因素。

举个例子,譬如某企业中应用的单体架构的 Java 系统,其更新、升级都必须要有固定的停机计划,必须在特定的时间窗口内才能按时开始,必须按时结束。如果出现了非计划的宕机,那便是生产事故。但是软件的缺陷不会遵循领导定下的停机计划来“安排时间出错”,为了应对缺陷与变化,做到不停机地检修,Java 曾经搞出了 OSGi 和 JVMTI Instrumentation 等这样复杂的 HotSwap 方案,以实现给奔跑中的汽车更换轮胎这种匪夷所思却又无可奈何的需求;而在微服务架构的视角下,所谓系统检修,不过只是一次在线服务更新而已,先停掉 1/3 的机器,升级新的软件版本,再有条不紊地导流、测试、做金丝雀发布,一切都是显得如此理所当然、平淡寻常;而在无服务架构的视角下,我们甚至都不可能去关心服务所运行的基础设施,连机器是哪台都不必知道,停机升级什么的就根本无从谈起了。

流水不腐,有老朽,有消亡,有重生,有更迭才是生态运行的合理规律。请设想一下,如果你的系统中每个部件都符合“Phoenix”的特性,哪怕其中某些部件采用了由极不靠谱的人员所开发的极不靠谱程序代码,哪怕存有严重的内存泄漏问题,最多只能服务三分钟就一定会崩溃。而即便这样,只要在整体架构设计有恰当的、自动化的错误熔断、服务淘汰和重建的机制,在系统外部来观察,整体上仍然有可能表现出稳定和健壮的服务能力。

凤凰架构

在企业软件开发的历史中,一项新技术发布时,常有伴以该技术开发的“宠物店(PetStore)”作为演示的传统(如 J2EE PetStore、.NET PetShop、Spring PetClinic 等等)。作为不同架构风格的演示时,笔者本也希望能遵循此传统,却无奈从来没养过宠物,遂改行开了书店(Fenix’s Bookstore),里面出售了几本笔者撰写过的书籍,算是夹带一点私货,同时也避免了使用素材时可能的版权问题。

尽管相信没有人会误解,但笔者最后还是多强调一句,Oracle、Microsoft、Pivotal 等公司设计宠物店的目的绝不是为了日后能在网上贩卖小猫小狗,只是纯粹的演示技术。所以也请勿以“实现这种学生毕业设计复杂度的需求,引入如此规模的架构或框架,纯属大炮打苍蝇,肯定是过度设计”的眼光来看待接下来的“Fenix’s Bookstore”项目。相反,如果可能的话,笔者会在有新的技术、框架发布出来时,持续更新,以恰当的形式添加到项目的不同版本中,可能使其技术栈越来越复杂。笔者希望把这些新的、不断发展的知识,融合进已有的知识框架之中,让自己学习、理解、思考,然后将这些技术连同自己的观点看法,传播给感兴趣的人。

也算是缘分,网名“IcyFenix”在二十多年前我的中学时代开始使用,最初它是来源于暴雪公司的即时战略游戏《星际争霸》的 Protoss 英雄 Fenix——如名字所预示的那样,他曾经是 Zealot,牺牲后以 Dragoon 的形式重生,带领 Protoss 与刀锋女王 Kerrigan 继续抗争。尽管中学时期我已经笃定自己未来肯定会从事信息技术相关的工作,但显然不可能预计到二十年后我会写下这些文字。

所以,既然我们要开始一段关于“Phoenix”的架构讨论与代码实践,那便叫它“凤凰架构”,如何?