网站伸缩性架构-永无止境

6、伸缩性-永无止境

架构的伸缩性设计

不同功能进行物理分离实现伸缩

纵向分离(分层后分离)
横向分离(业务分割后分离)
在这里插入图片描述
在这里插入图片描述

单一功能通过集群规模实现伸缩

当一头牛拉不动车的时候,不要去寻找一头更强壮的牛,而是用两头牛来拉车。

应用服务器集群的伸缩性设计

HTTP 重定向负载均衡

在这里插入图片描述
根据请求,计算一个服务器地址,利用 HTTP 302 重定向到服务器地址。
优点:
比较简单。
缺点:
浏览器需要两次请求服务器才能完成一次访问,性能较差;
重定向服务器自身的处理能力可能成为性能瓶颈;
302 重定向可能被搜索引擎判断为 SEO 作弊,降低搜索排名。

DNS 域名解析负载均衡

在这里插入图片描述
在 DNS 服务器中配置多个 A 记录,如: www.xxx.com IN A 114.100.80.1 和 www.xxx.com IN A 114.100.80.2。每次域名解析请求都会根据负载均衡算法计算一个不同的 IP 地址返回。
优点:
负载均衡工作转交给 DNS,省去了一些工作内容。
DNS 还支持基于地理位置的域名解析。
缺点:
DNS 多级解析,每一级 DNS 都可能缓存 A 记录,当某台服务器下线后,即使修改了 A 记录,也得等一会才能生效。

可以部分使用 DNS 域名解析,解析作为第一级负载均衡手段,即解析得到的一组服务器并不是真正提供 Web 服务的物理服务器,而是同样提供负载均衡的内部服务器。

反向代理负载均衡

在这里插入图片描述
反向代理服务器转发请求在 HTTP 协议层面,因此也称为 应用层负载均衡。
优点:
和反向代理服务器功能集成在一起,部署简单。
缺点:
反向代理服务器是所有请求和响应的中转站,性能可能会成为瓶颈。

IP 负载均衡

在这里插入图片描述
SNAT 源地址转换!
优点:
IP 负载均衡在内核进程中完成数据分发,比反向代理负载均衡(在应用层分发)有更好的性能;
缺点:
所有请求和响应都要经过负载均衡服务器,集群最大相应数据屯独立受制于负载均衡服务器网卡带宽;

数据链路负载均衡

在这里插入图片描述
在通信协议的数据链路层修改 mac 地址进行负载均衡。
这种负载均衡方式又称作直接路由方式(DR)。
也称为三角模式。
在 Linux 上比较好的开源产品是 LVS(Linux Virtual Server)

负载均衡算法

负载均衡服务器的实现可以分为 2 个部分:
1、根据负载均衡算法和 Web 服务器列表得到集群中一台 Web 服务器的地址。
2、将请求数据发送到该地址对应的 Web 服务器上。

轮询(Round Robin,RR)

适用于所有服务器硬件都相同的场景。

加权轮询(Weighted Round Robin,WRR)

根据硬件性能,高性能服务器能分配更多请求。

随机(Random)

简单实用,随机数本身就很均衡。
也可以改一改成为加权随机法。

最少连接(Least Connections)

记录每个服务器正在处理的连接数(请求数),新请求发给连接数最少的那个。
同样可以实现个加权最少连接。

源地址散列(Source Hashing)

一个 IP 地址进行 Hash 得到应用服务器地址,这样来自同一个 IP 地址的请求总在同一个服务器上处理,该请求的上下文信息可以存储在这台服务器上,在一个会话周期内复用,从而实现会话粘滞。

分布式缓存集群的伸缩性设计

Memcached 分布式缓存集群的访问模型

set(key, data)、get(key)
路由根据 key 计算对应应该从哪台服务器写缓存,从哪台服务器读缓存。

Memcached 分布式缓存集群的伸缩性挑战

对于集群的管理,路由算法至关重要,决定着究竟该访问集群中的哪台服务器。
简单的路由算法就是余数 Hash。
对于余数 Hash,当集群需要扩容的时候,事情就比较糟糕了。
假设 3 台缓存服务器需要扩容到 4 台,更改服务器列表,依然使用余数 Hash,用 4/key 的 Hash 值大约有 75%(3/4) 不能正确命中,随着服务器集群规模的增大,这个比例直线上升!
当 100 台集群中增加一台,不能命中的概率是 99%( n/(n+1) )。

大部分的业务数据读操作请求事实上是通过缓存获取的,只有少量的操作请求会访问数据库。
当大量的缓存出现不能命中时,对于数据库的压力就很大了,甚至宕机。

一种解决方法就是在网站访问了最少的时候进行缓存服务器集群扩容,然后通过模拟请求的方法来预热缓存。
另一种方法就是通过下面的算法了!

分布式缓存的一致性 Hash 算法

一致性 Hash 算法通过一个叫做一致性 Hash 环的数据结构实现 KEY 到缓存服务器的 Hash 映射。
image.png
具体算法过程为:
先构造一个长度为 2^32 的整数环,这个环被称为一致性 Hash 环。
根据节点名称的 Hash 值(其分布范围为[0, 2^32-1])将缓存服务器节点放置在这个 Hash 环上。
然后根据需要缓存的数据 KEY 的值计算得到其 Hash 值(分布范围同上)。
然后在 Hash 环上顺时针找举例这个 KEY 的 Hash 值最近的缓存服务器节点,完成 KEY 服务器的 Hash 映射查找。

当缓存服务器集群需要扩容的时候,只需要将新加入的节点名称(NODE3)的 Hash 值放入一致性 Hash 环中,由于 KEY 是顺时针查找举例其最近的节点,因此新加入的节点只影响整个环中的一小段。
image.png
3台 -> 4台扩容时候的命中率是 75%,远高于余数 Hash 的 25%。

在具体应用中,这个长度为 2^32 的一致性 Hash 环通常使用二叉查找树实现,Hash 查找过程实际上是在二叉查找树中查找不小于查找数的最小数值,这个数的最左叶子节点和最右叶子节点连接构成环。

但是!这个过程还存在一些小问题!

新加入的节点 NODE3 只影响了原来的节点 NODE1,也就是说一部分原来需要访问 NODE1 的缓存数据现在需要访问 NODE3(概率上市 50%)。
但是原来的节点 NODE0 和 NODE2 不受影响,这就意味着 NODE0 和 NODE2 缓存数据量和负载压力是 NODE1 和 NODE3 的两倍。
如果这 4 台机器性能是一样的,那么这种结果不是想要的。

怎么办?

计算机的任何问题都可以通过增加一个虚拟层来解决!
计算机硬件、计算机网络、计算机软件都莫过于此。
计算机网络7层,每一层可以看做是下一层的虚拟层;计算机操作系统可以看做是硬件的虚拟层;JVM 可以看作是操作系统的虚拟层;分层软件架构事实上也是如此。

将每台物理缓存服务器虚拟为一组虚拟缓存服务器,将虚拟服务器的 Hash 值放置在 Hash 环上,KEY 在环上先找到虚拟服务器节点,再得到物理服务器信息。

这样在新加入物理服务器节点时,是将一组虚拟节点加入环中,如果虚拟节点的树木足够多,这组虚拟节点将会影响同样多树木的已经在换上存在的虚拟节点,这些已经存在的虚拟节点又对应不同的物理节点。
最终结果是:新加入一台缓存服务器,将会较为均匀的影响原来及群众已经存在的所有服务器,也就是说分摊原有缓存服务器集群中所有服务器的一小部分负载。

image.png
如上图,加入 NODE3 对应的一组虚拟节点为 V30 V32 V32,加入到一致性 Hash 环上后,影响 V01 V12 V22
这三个被影响的虚拟节点对应 NODE0 NODE1 NODE2 三个物理节点。
最终加入一个节点,影响三个物理节点,理想情况下,每个物理节点收到影响的缓存数据量是 1/4 (x/ (x+n)),N 为原物理节点数,X 为新加入物理节点数。也就是及群众已经被缓存的数据有 75% 可以被命中。

理论上虚拟节点数越多,物理节点之间的负载就越均衡。
但是太多影响性能,太少负载不均衡,一般来说经验是 150,根据集群规模和均衡的精度需求,具体对待。

数据存储服务器集群的伸缩性设计

关系数据库集群的伸缩性设计

分库分表,质数。

NoSQL 数据库的伸缩性设计

NoSQL 更关注高可用性和可伸缩性。
舍弃了以关系代数为基础的结构化查询语言(SQL)和事务一致性保证(ACID)。


EOF!

阅读全文
高可用网站架构-万无一失

高可用-万无一失

廉价的服务器硬件故障是常态,网站的高可用架构设计的主要目的就是保证服务器硬件故障时服务依然可用、数据依然保存并能够访问。
实现上述高可用方案的主要数据和服务的手段是冗余备份和失效转移。


应用层:应对高并发,负载均衡,心跳检测监控,不可用时候剔除。
服务层:通过集群方式实现高可用,被应用层通过分布式调用框架访问,分布式调用框架会在客户端程序中实现软件负载均衡、心跳检测。
数据层:同步复制,冗余备份。

高可用的应用

健身房小姐姐填表单的栗子。
无状态性!!!


可以直接通过负载均衡实现无状态服务的负载均衡。


应用服务器集群的 Session 管理
事实上,业务总是有状态的,在交易类的电商网站需要有购物车记录的购买信息,用户每次购买请求都是向购物车中增加商品;在社交类网站中,需要记录用户的当前登录状态、最新发布的消息和好友列表等,每次刷新页面都需要更新这些信息。

  1. Session 复制

应用服务器开启 Web 容器的 Session 复制功能,在集群中的几台服务器之间同步 Session 对象,每台服务器保存所有用户的 Session 信息。
当集群规模较大时候,大量的 Session 复制通信占用服务器的网络资源较大,甚至有内存不够存 Session 情况。

  1. Session 绑定

Session 绑定可以利用负载均衡的源地址 Hash 算法实现,总是将同一个 IP 的请求分发到同一台服务器上,也可以根据 Cookie 信息将同一个用户的请求分发到同一台服务器上。这个负载均衡服务器必须工作在 HTTP 协议层上。这样就能保证这个用户的请求都在同一台服务器上,这种方法又被成为会话粘滞。
但是 Session 绑定的方案不符合高可用程序,某台服务器宕机后一些依赖此服务器的用户的服务就不可用了。

  1. 利用 Cookie 记录 Session
    1. Cookie 大小限制,记录信息有限
    2. 每次响应都要传输 Cookie,影响性能
    3. 如果用户关闭 Cookie 功能,访问就会不正常
  2. Session 分离

独立的 Session 服务器或者集群,基础服务平台。

高可用的服务

可复用的服务和应用一样,也是无状态的服务,此可以使用类似负载均衡的失效转移策略实现高可用服务。

  1. 分级管理
    1. 核心应用和服务优先使用更好的硬件,运维响应时间也要迅速
  2. 超时设置
    1. 超时后继续重试或者将请求失效转移到提供相同服务的其他服务器上
  3. 异步调用
    1. 消息队列等异步调用的方式
  4. 服务降级
    1. 拒绝服务?关闭服务?
    2. 拒绝服务:拒绝优先级低的应用调用,减少服务器的并发数,保证核心功能正常调用;或者随机拒绝部分请求调用,节约资源。
    3. 关闭服务:关闭不中哟的部分服务,或者服务内部关闭部分不重要的功能。
  5. 幂等性设计
    1. 服务重复调用是无法避免的,应用层也不需要关心服务是否真的失效,只要没有得到调用成功的响应,就可以认为调用失效,并充实服务调用。因此必须在服务层保证服务重复调用和调用一次产生的结果相同,即服务具有幂等性。

高可用的数据


数据备份和失效转移机制。


为了保证数据的高可用,网站通常会牺牲另一个很重要的指标:数据一致性。

CAP 原理
数据持久性
数据可访问性
数据一致性**

  1. 数据强一致
  2. 数据用户一致
  3. 数据最终一致

数据备份

异步热备份、同步热备份
在这里插入图片描述
在这里插入图片描述

失效确认

在这里插入图片描述

访问转移

转移到存储的数据完全一样的服务器上(对等服务器)
如果服务不对等,就需要重新计算路由,选择存储服务器。

数据恢复

。。。

软件质量保证

网站发布

飞行中给飞机换个引擎。

自动化测试

全面的回归测试。

预发布验证

预发布机器。

代码控制

主干发布,分支开发。
主干开发,分支发布。
~~

自动化发布

灰度发布

第一天发布 0~999 服务器,遇到故障回滚。
第二天发布 1000~1999 服务器,遇到故障回滚。
。。。

网站运行监控

不允许没有监控的系统上线。

监控数据采集

  1. 用户行为日志收集
    1. 服务端日志手机
    2. 客户端浏览器日志收集
  2. 服务器性能监控
  3. 运行数据报告

监控管理

  1. 系统报警
  2. 失效转移
  3. 自动优雅降级

EOF!

阅读全文
高性能网站架构-瞬时响应

高性能-瞬时响应

检查请求各个环节的诶之,分析哪个环节响应时间不合理、超出预期;
检查监控数据,分析影响性能的主要因素是内存、磁盘、网络、还是 CPU,是代码问题还是架构设计不合理,或者系统资源确实不足。

性能测试指标

响应时间、并发数、吞吐量、性能计数器等。

响应时间

每个响应时间比较短不好测试,常用方法是重复请求很多次,求平均时间。

并发数

系统能够同时处理请求的数目,对于网站而言,指同时提交请求的用户数目。


测试程序通过多线程/协成模拟并发用户的办法来测试系统的并发处理能力,为了真实的模拟用户行为,测试程序并不是启动多线程后不停地发送请求,而是再两次请求中间加入一个随机等待时间,被称为思考时间。

吞吐量

TPS(每秒事务数)
HPS(每秒HTTP请求数)
QPS(每秒查询数)

性能计数器

System Load、对象与县城数、内存使用、CPU 使用、磁盘与网络 I/O 等指标。
系统监控、报警。


System Load(系统负载),指当前正在被 CPU 执行和等待被执行的进程数目总和,是反应系统忙闲程度的重要指标。
Load 理想值是 CPU 数目,Load 高于 CPU 数目的时候表示系统资源不足,影响程序的执行性能。

top 命令查看,3 个浮点数,表示最近 1min、5min、15min 运行队列平均进程数。

性能优化

前端性能优化

减少 HTTP 请求

合并 CSS 文件、合并 JS 文件、合并图片、懒加载等。

使用浏览器缓存

缓存 CSS、JS、Logo、图表等静态资源。
通过设置 HTTP 头中的 Cache-Control 和 Expires 属性,控制浏览器的缓存。

有时候静态资源变化需要及时应用到浏览器,可以通过修改文件名实现,即更新 JS 文件并不更新 JS 文件内容。

逐渐更新:一次更新一部分图标文件等等。

启用压缩

文本文件的压缩可达 80% 以上,因此 HTML、CSS、JS 通过启用 GZip 压缩可以达到好的效果,但是压缩对服务器和浏览器会产生一定的压力,在网络状况好的情况下要权衡考虑。

CSS 放在页面最上面,JS 放在页面最下面

浏览器会在下载完全部的 CSS 后才对网页进行渲染。
浏览器在加载 JS 后立即执行,有可能阻塞整个页面。

减少 Cookie 次数。Cookie 会包含在每次的请求和响应中,太大的 cookie 会影像数据传输。
静态资源的传输,有时候带上 Cookie 没有意义,有的时候有意义(比如图片验证码)。

CDN 加速

emmm 类似于缓存

反向代理

emmm 类似于缓存

服务端性能优化

网站性能优化第一定律:优先考虑缓存优化性能。

分布式缓存

注意要合理使用缓存。缓存穿透、雪崩、击穿!!!
频繁修改的数据!
没有热点的访问!
数据不一致和脏读!
缓存可用性!


缓存预热!

异步操作

消息队列等。
消息队列(削峰作用)。

使用集群

配置负载均衡。

代码优化

多线程、协成。
资源使用统一管理(池,进程池、线程池、连接池、对象池、单例)

数据结构

哈希?

垃圾回收

。。。

存储性能优化

机械硬盘、固态硬盘。

B+树、LSM 树。

传统的关系数据库使用的是 B+ 树,层次最多三层。
现在很多 NoSQL 数据库使用 LSM 树。

存储阵列

RAID0、RAID1、RAID10、RAID5、RAID6。
HDFS 中,系统在整个存储集群的多态服务器上进行数据并发读写备份,可以看做在服务器集群规模上上线了类似 RAID 的功能,因此不需要磁盘 RAID。
MapReduce 并发访问,迁移计算而不是不迁移数据。


HDFS 中两个重要的服务器角色:NameNode(名字服务器节点)和 DataNode(数据存储节点)。
NameNode 在 HDFS 中只部署一个实例,提供元数据服务,相当于操作系统中的文件分配表 FAT,管理文件名 Block 的分配,维护整个文件系统的结构。
DataNode 则部署在 HDFS 集群中其他所有服务器上,提供真正的数据存储服务。




阅读全文
大型网站架构核心要素

大型网站核心架构要素

性能

浏览器端:浏览器缓存、页面压缩、合理页面布局、减少 Cookie 传出、CDN。
应用服务器端:本地缓存、分布式缓存、异步操作、服务器集群。
代码层面:多线程、改善内存管理等。
数据库端:索引、缓存、SQL 优化等性能优化手段、NoSQL 优化数据模型、存储结构、伸缩性。

可用性

假设系统中任何一台或多台服务器宕机时,以及出现各种不可预期的问题时,系统整体依然保持可用。
提高网站可用性的主要手段是冗余。
1、对于应用服务器,多台服务器负载均衡,前提是应用服务器上不能保存请求的回话信息(小姐姐小哥哥游泳健身表单)。
2、对于存储服务器,实时热备份。
3、开发过程质量保证,预发布验证、自动化测试、自动化发布、灰度发布,减少将故障引入线上环境。

伸缩性

所谓伸缩性是指通过不断向及群众加入服务器的手段来缓解不断上升的用户并发访问压力和不断增长的数据存储需求。

1、对于应用服务器集群,只要服务器上不保存数据,所有服务器都是对等的,通过合适的负载均衡设备就可以向进群中不断添加服务器。
2、对于缓存服务器集群,加入新的服务器可能会导致缓存路由失败,进而导致及群众大部分缓存数据无法访问。虽然缓存的数据可以通过数据库重新加载,但是如果应用已经严重依赖缓存,可能会导致整个网站崩溃,需要改进缓存路由算法保证缓存数据的可访问性。
3、数据库虽然支持数据复制,主从热备等机制,但是很难做到大规模集群的可伸缩性,因此关系数据库的集群伸缩性方案必须在数据库之外实现,通过路由分区等手段将部署有多个数据库的服务器组成一个集群。

至于 NoSQL 数据库,天生就是为海量数据而生,伸缩性通常都非常好。

扩展性

增加新的业务产品时,是否可以实现对现有产品透明吴映香,不需要任何改动或者很少的搞懂现有业务功能就可以上线新的产品。不同产品之间的少耦合。
网站可扩展架构的主要手段是事件驱动和分布式服务。

事件驱动架构在网站通常利用消息队列来实现,分布式服务则是将业务和可复用服务分离开来,通过分布式服务框架调用。

安全性

现存和潜在的攻击和窃密手段,是否有可靠的应对策略。


EOF

阅读全文
大型网站架构模式

大型网站架构模式

每一个模式描述了一个在我们周围不断重复大声的问题以及问题解决方案的核心。

分层

将系统横向切分。
分层结构在计算机中无处不在,网络的 ISO 7层分层,计算机硬件、操作系统、应用软件也是一种分层。
网站系统中:应用层、服务层、数据层。
分层架构的挑战:合理规划层次边界和接口。
进制跨层次的调用(应用层直接调用数据层)和逆向调用(数据层调用服务层,或者服务层调用应用层)。

分割

将系统纵向切分。
将每一层按模块进行分割,每个模块由不同的团队负责。

分布式

分布式应用和服务、分布式静态资源、分布式数据和存储、分布式计算(Hadoop 的 MapReduce 分布式计算框架,移动计算而不是移动数据)。

集群

使用分布式已经将分层和分割后的模块独立部署,但是对于用户访问集中的模块(比如网站首页),还需要将独立部署的服务器集群化,即多态服务器部署相同应用构成一个集群,通过负载均衡设备共同对外提供服务。

缓存

CDN、反向代理、本地缓存、分布式缓存。
使用缓存有两个条件:
1、数据访问热点不均衡,某些数据会被更频繁的访问;
2、数据再某个时间段内有效,不会很快过期,否则缓存的数据会因已经失效而产生脏读,影响正确性。

异步

单一服武器内部可以通过多线程共享内存队列的方式实现异步,业务线程将输出写入队列,处理线程从队列读取进行处理;
分布式系统中,多个服务器集群通过分布式消息队列实现异步(内存队列的分布式部署)。
异步架构是典型的生产者消费者模型,两者不存在直接调用,只需要保持数据结构不变,彼此功能实现可以随意变化而不相互影响,这对网站拓展新功能非常便利。

使用异步队列还有如下特性:
1、提供系统可用性,消费者服务器故障,数据再消息队列中堆积,生产者继续处理就可以了。
2、加快网站响应速度,业务端将请求写入消息队里,不需要等待消费者处理就可以返回。
3、消除并发访问高峰,消息队列将突然增加的访问请求数据放入消息队列中,等待消费者服务器依次处理。

冗余

定期备份,冷备份。
主从热备份。
容灾数据中心。
去中心化。

自动化

发布过程自动化、自动化代码管理、自动化测试、自动化安全监测、自动化部署、自动化监控、自动化报警、自动化失效转移、自动化失效恢复、自动化降级(网站遇到高峰超出处理能力,为了保证整个网站安全可用,关闭一些不用的服务或者拒绝部分请求)、自动化分配资源。

安全

加密、安全校验、风险控制。


EOF

阅读全文