1. 简介
1.1. 在过去20年里,软件系统的规模、复杂性和容量都出现了前所未有的增长
1.2. 代码是容器、数据库、消息传递系统和其他组件的一部分,通过调用API和构建指令,构成你的应用程序
1.3. 可扩展(scalable)是软件工程中用来描述软件系统能够适应增长的术语
- 1.3.1. 可扩展性是一个非常简单的概念
1.4. 快速且低成本地扩展应用程序的能力应该是当代面向互联网的应用程序的软件架构的决定性质量
2. 定义
2.1. 维基百科对它的定义是“可扩展性是通过添加更多资源来处理越来越多的工作的系统属性”
2.2. 与物理系统不同,软件系统在某种程度上是无定形的
-
2.2.1. 它们并非是通过外部观察就能了解其内部行为的东西
-
2.2.2. 一个软件系统就是一个数字工件(artifact)
2.3. 不同运营维度的例子
-
2.3.1. 系统可以同时处理的来自用户或外部设备(例如传感器)的请求的数量
-
2.3.2. 系统可以有效处理和管理的数据量
-
2.3.3. 对系统存储的数据进行预测分析而获得的价值
-
2.3.4. 随着请求量的增长,系统保持稳定、一致的响应时间的能力
2.4. 在开发和部署的早期阶段,可扩展性并不是主要的质量要求
- 2.4.1. 在有明确的需求之前引入一些复杂的分布式技术可能对项目有害,额外的复杂性会导致开发过于保守
2.5. 成功扩展系统关系到许多现代互联网应用程序的生存问题
- 2.5.1. 在系统的发展过程中,提高系统性能和可扩展性成为当务之急甚至影响系统存亡的现象比比皆是
2.6. 往往存在一个临界点,在轻负载下有意义的设计和决策突然变成了技术债务
2.7. 通过增加资源来增加系统在某个维度上的容量称为纵向扩展(scaling up)或横向扩展(scaling out)
2.8. 与物理系统不同,能够按比例缩小(scale down)系统容量以降低成本同样重要
- 2.8.1. 一个非常典型的例子是Netflix,它需要处理来自不同区域的可预测的昼夜请求
2.9. 案例
-
2.9.1. Scribe是一种自定义缓存队列解决方案,它可以以每秒几TB的速率从服务器传输日志,并将它们传送到下游分析和数据仓库系统中
-
2.9.2. 互联网站点提供的关于服务规模的真实且具体的数据仍然是商业机密
3. 软件系统发展简史
3.1. 1980~1989
-
3.1.1. 一个由分时主机和小型机主宰的时代
-
3.1.2. 个人计算机出现于20世纪80年代初期,但很少联网
-
3.1.3. 万维网在20世纪80年代诞生于欧洲核子研究中心(CERN),由Tim Berners-Lee首创
3.2. 1990~1995
-
3.2.1. 网络变得更加普遍,为基于HTTP/HTML的万维网(WWW)技术的出现创造了成熟的环境
-
3.2.2. 1994年雅虎(Yahoo!)创立
-
3.2.3. 1995年亚马逊和eBay诞生
3.3. 1996~2000
-
3.3.1. 网站数量从10000左右增长到1000万
-
3.3.2. 亚马逊、eBay、谷歌和雅虎等公司已经开创了许多设计原则和先进技术的早期版本
3.4. 2001~2006
-
3.4.1. 网站数量从约1000万个增长到8000万个
-
3.4.2. 2005年,YouTube推出
- 3.4.2.1. 第一次上传视频到YouTube发生在2005年
-
3.4.3. 2006年,Facebook向公众开放
- 3.4.3.1. 亚马逊网络服务(AWS)重新推出了S3和E C2服务
3.5. 2007至今
-
3.5.1. 大约拥有20亿个网站
-
3.5.2. 大约有40亿互联网用户
4. 可扩展性系统设计基本原则
4.1. 扩展系统的基本目标是在应用程序的某些特定维度上增加容量
4.2. 一个常见的维度是增加系统在给定时间段内可以处理的请求数量
- 4.2.1. 系统的吞吐量
4.3. 复制
-
4.3.1. 在软件系统中增加容量的第一个策略
-
4.3.2. 我们基本上复制了软件中处理请求的资源,以提供更多的请求处理能力,从而提高吞吐量
-
4.3.3. 在基于云的软件系统中,只需点击鼠标即可实现复制,我们可以有效地复制用来处理请求的资源,高达数千倍
4.4. 优化
-
4.4.1. 如果我们通过以下方法可以优化请求的处理,那么可以在不增加资源的情况下提高系统能力
-
4.4.1.1. 使用更有效的算法
-
4.4.1.2. 在数据库中添加额外的索引以加快查询速度
-
4.4.1.3. 用更快的编程语言重写服务器
4.4.1.3.1. Facebook创建的用于PHP的HipHop
4.4.1.3.2. HipHop将PHP代码编译为C++,将Facebook的网页生成速度提高了6倍
-
5. 可扩展性与成本
5.1. 对于某些应用程序,需要承担修改业务系统来满足最终业务需求的成本
5.2. 不应该期望一个没有采用可扩展架构、机制和技术的软件系统快速发展以满足更大的容量需求
5.3. 在成本线性增长的同时支持指数级扩展的软件系统被称为超大规模系统
6. 权衡
6.1. 可扩展性是非功能性需求,它只是众多质量属性之一
6.2. 经验丰富的软件架构师非常注意分寸,他们精心设计系统来满足高优先级的质量属性,同时尽量减少对其他质量属性的负面影响
7. 可用性
7.1. 可用性和可扩展性通常是高度兼容的“合作伙伴”
-
7.1.1. 当我们复制资源来扩展自己的系统时,我们创建了多个服务实例,可用于处理来自任何用户的请求
-
7.1.2. 如果一个实例出现故障,则其他实例仍然可用
-
7.1.3. 系统容量减少的原因只是应用程序出现故障或资源不可用
7.2. 可用性是指系统即使在对手的攻击下也仍然保持可靠运行的能力
7.3. 来自对手的攻击可能是试图利用系统设计弱点使系统瘫痪
7.4. 另一种攻击则是经典的分布式拒绝服务(DDoS),在这种攻击中,对手获得了对众多系统和设备的控制权,并协同大量请求,使得受害系统不可用
8. 安全性
8.1. 安全系统的基本要素是身份验证、授权和数据完整性
8.2. 安全性是所有面向互联网的系统的必要质量属性
8.3. 构建安全系统的成本是不可避免的
8.4. TLS使用非对称加密提供加密、身份验证和数据完整性能力
-
8.4.1. 由于双方都需要生成和交换密钥,所以会产生性能成本
-
8.4.2. 建立连接后,传输中的数据将使用对称加密技术进行加密,由于现代CPU具有专用的加密硬件,因此这部分的性能损失可以忽略不计
-
8.4.3. 建立连接通常需要在客户端和服务器之间进行两次消息交换,因此速度较慢
-
8.4.4. 尽可能重用连接可以最大限度地减少性能开销
8.5. 保护静态数据
-
8.5.1. SQL Server和Oracle等流行数据库引擎具有透明数据加密(TDE)等功能,可提供高效的文件级加密
-
8.5.2. 静态安全数据的开销是实现安全性必须承担的成本
- 8.5.2.1. 研究表明开销在5%~10%的范围内
8.6. 一般来说,安全性和可扩展性是对立的力量
-
8.6.1. 安全必然会导致性能下降
-
8.6.2. 系统包含的安全层越多,性能和可扩展性的负担就越大
9. 可管理性
9.1. 用于描述这种复杂监控功能的术语是可观测性
9.2. 指标对于洞察系统是非常宝贵的,它有助于确保持续运营,以及凸显系统中可能需要优化或复制的部分
9.3. 扩展系统总是意味着添加新的系统组件——硬件和软件
- 9.3.1. 它增加了系统操作的复杂性和监控成本,这需要开发更多的监控代码来调整可观测平台,确保其监控了新的系统组件
9.4. 在扩展时,控制成本和可管理性的复杂性的唯一方法是自动化
9.5. DevOps自动执行系统的持续测试、部署、管理、升级和监控,缩短了新功能的开发生命周期
- 9.5.1. 它是所有成功的可扩展系统的组成部分