1. 核心要素
- 性能
- 可用性
- 伸缩性
- 拓展性
- 安全性
五个要素能不能都要呢?
2. 性能
网站的性能是客观的指标,可以具体体现到响应时间、吞吐量等技术指标,同时也是主观感受。
用户视角的性能:
就是用户在浏览器上直观感受到的网站响应速度快还是慢。
开发人员眼中的性能:
- 响应延迟
- 系统吞吐量
- 并发处理能力
- 系统稳定性等
相关的优化手段有:
- 缓存加速读取
- 使用集群提高吞吐能力
- 使用异步消息加快请求响应及实现削峰
- 使用代码手段优化
运维人员视角的性能主要是基础设施性能和资源利用率,包括:
- 网络运营商的带宽能力
- 服务器硬件配置
- 数据中心网络结构
- 服务器和带宽的资源利用率
主要优化手段:
- 建设优化骨干网
- 高性价比定制服务器
- 利用虚拟化技术优化资源
性能测试指标主要有:
-
*响应时间
-
并发数
反映系统的负载特性
网站系统用户数>>网站在线用户数>>网站并发用户数
-
吞吐量
体现系统的整体处理能力,TPS、HPS和QPS
-
性能计数器
性能测试方法:
- 性能测试——性能预期测试
- 负载测试——安全临界值测试
- 压力测试——最大压力承受能力测试
- 稳定性测试——长时间运行稳定性测试
性能优化策略:
思路:如果性能测试结果不满足设计或业务需求,那么就需要寻找系统瓶颈,分而治之,逐步优化
-
性能分析
基本方法:检查请求处理的各个环节日志,分析哪个环节响应时间不合理、超过预期;然后检查监控数据,分析影响性能的主要因素是内存、磁盘、网络或CPU,是代码还是架构设计不合理,或者系统资源确实不足。
-
性能优化
根据网站分层架构,可分为Web前端性能优化、应用服务器性能优化、存储服务器性能优化。
2.1 Web前端性能优化
主要优化手段:优化浏览器访问、使用反向代理、CDN
2.1.1 浏览器访问优化
-
减少HTTP请求
-
使用浏览器缓存
-
启用压缩
-
CSS放最上面,JS放最先
浏览器会在下完全部CSS后才对页面进行渲染,最好的做法是将CSS放在最上面,尽快下载CSS。JS相反,浏览器在加载JS后立即执行,有可能会阻塞整个页面,造成显示缓慢,因此JS最好放在页面最下面。
-
减少cookie传输
2.1.2 CDN加速
2.1.3 反向代理
反向代理的功能= 请求转发+负载均衡+缓存
2.2 应用服务器性能优化
优化手段主要有缓存、集群和异步
网站性能优化第一定律:优先考虑使用缓存优化性能
2.2.1 分布式缓存
缓存穿透 缓存击穿 缓存雪崩
缓存的优势在于:1. 提升IO速度;2. 减少重复计算,同时因为局部性原理的存在,所以缓存很实用
合理使用缓存
使用缓存要注意的问题:
- 频繁修改的数据——刚放了就修改
- 没有热点的访问——存错数据了
- 数据不一致与脏读——实时更新的问题
- 缓存可用性——缓存的稳定性
- 缓存预热——设置缓存的时候加载热点数据
- 缓存穿透——没有命中,都落到数据库上
- 缓存击穿——部分热门数据key过期,导致查询落到数据库上
- 缓存雪崩——大面积的key过期,导致查询直接落到数据库上
一个集群要解决什么问题?
分布式缓存集群的第一个问题:各个集群直接需不需要互相通信?需不需要同步?
代表之作,Memcached,一致性哈希算法等路由算法
Memcached的特点:
-
简单的通信协议
使用TCP协议
-
丰富的客户端程序
支持Memcached的通信协议就可以和Memcached的机器通信
-
高性能的网络通信
通信模块:Libevent,一个支持事件出发的网络通信程序库。
-
高效的内存管理
固定空间分配,使用LRU算法。
-
互不通信的服务器集群架构
使其拥有更好的伸缩性,几乎可以做到线性增长。
2.2.2 异步操作
主要是消息队列。
- 可以削峰
名言:任何可以晚点做的事情都应该晚点再做
2.2.3 使用集群
将请求分散到集群上的不同机器去解决。
2.2.4 代码优化
-
多线程(多协程)
解决线程安全的一些手段:
- 将对象设计为无状态对象
- 使用局部对象
- 并发访问资源时使用锁
-
资源复用
主要的复用方法:减少资源创建时的消耗
- 资源池
- 单例模式
-
数据结构
随机散列算法一般是通过先对字符串取信息指纹,再对信息指纹取hashcode。
-
垃圾回收
提高利用率。
2.3 存储服务器性能优化
2.3.1 机械硬盘vs固态硬盘
2.3.2 B+树vs LSM树
B+树:
B+树一般两层索引,最后一层是叶子ID,一般更新一个记录需要5次磁盘IO(三次磁盘访问获得数据索引及行ID,然后再进行一次数据文件读操作及一次写操作)
LSM树(日志结构合并树):https://zhuanlan.zhihu.com/p/181498475
LSM树一般用在NoSQL数据库。简单介绍一下,之后必须要补充一下LSM树的结构。
LSM树可以看成是N阶合并树,数据写操作都在内存中进行,并且都会创建一个新纪录(修改会记录新数据值,而删除会记录一个删除标志),这些数据在内存中仍然还是一颗排序树,当数据量超过设定的内存阈值后,会将这颗排序树与磁盘上最新的排序树合并。当这颗排序树的数据量也超过设定阈值后,和磁盘上下一级的排序树合并。合并过程中,会用最新更新的数据覆盖旧的数据(或者记为不同版本)。在需要读时,从内存开始,再去磁盘。可以极大地减少磁盘访问次数,加快速度。
如果要查找以前的数据,性能会比较差。适合读最近数据比较多,写操作集中在最近数据的情况。
2.3.3 RAID vs HDFS
RAID廉价磁盘冗余阵列技术主要是为了改善磁盘的访问延迟,增强磁盘的可用和容错能力。本质上是用多块磁盘,提供并发读写和数据备份。
一般有六档:
-
RAID0
不做备份,将数据分成N份写入N块磁盘,速度提升N倍。
-
RAID1
将一份数据同时写入两块磁盘。
-
RAID10
将所有磁盘均分成两份,数据同时在两份磁盘写入,但是在每一份磁盘里面的N/2块磁盘上,利用RAID0技术并发读写。利用率较低。
-
RAID3
将数据分成N-1份写入N-1块磁盘,第N块磁盘写入1+2+3+…+N-1块磁盘的数据,这样当有一块磁盘损坏时可以恢复。
-
RAID5
与3类似,但是校验数据不是写入第N块磁盘,而是螺旋式地写入所有磁盘。
-
RAID6
和5类似,但是用了2块磁盘存储数据(所以只有N-2块能用),并螺旋式地在两块磁盘中写入校验信息。
HDFS(Hadoop分布式文件系统):
系统在整个存储集群的多台服务器上进行数据并发读写和备份,可以看做在服务器集群上实现了类似RAID的功能。
3. 可用性
网站的高可用架构设计的主要目的就是保证服务器硬件故障时服务依然可用、数据依然保存并且能被访问。
怎么实现?每个节点down了都有副节点可以实时切换。
主要手段有:
- 数据和服务的冗余备份
- 失效转移
一个网站设计典型的是三层架构模型:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TydYT7MZ-1641920364303)(C:\Users\Lao qigui\AppData\Roaming\Typora\typora-user-images\image-20220109005118836.png)]
应用层主要负责具体业务逻辑处理;服务层负责提供可复用的服务;数据层负责数据的存储与访问。
原则:大型网站的分层架构及物理服务器的分布式部署使得位于不同层次的服务器具有不同的可用性特点。关闭服务器或者服务器宕机时产生的影响也不相同,高可用的解决方案也差异甚大。
(集群YYDS)
- 应用层:为了高并发的请求,会通过负载均衡设备将一组服务器组成一个集群共同对外提供服务,当负载均衡设备通过心跳检测等手段监控到某台服务器不可用时,就将其从集群列表中剔除,并将请求分发到其它可用设备上。
- 服务层:同样通过集群,不过这些服务器被应用层通过分布式服务调用框架访问,分布式服务调用框架会在应用层客户端程序中实现软件负载均衡,并通过服务注册中心对提供服务的服务器进行心跳检测,发现有服务不可用,立即通知客户端程序修改服务访问列表,剔除不可用的服务器。
- 数据层:比较特殊,需要实现同步更新到多台服务器上,实现冗余备份。
一个集群需要一个master作为任务的分发,同时监听各个机器的状态。
3.3 高可用的应用
应用的一个显著特点(必备):无状态性。也即服务器不保存业务的上下文信息,仅仅根据每次请求提交的数据进行相应的业务逻辑处理,多个服务器实例之间完全对等,这样就使得请求提供到任意服务器都是一样的
3.3.1 通过负载均衡服务器进行无状态服务的失效转移
3.3.2 应用服务器集群的Session管理
总归不可能全部无状态。
Session管理的手段:
-
Session复制
消耗太大,比较占内存,适合小型集群
-
Session绑定
会变成会话粘滞(Session绑定服务器),缺点是该服务器宕机,那么相关的Session都会消失
-
利用Cookie记录Session
局限性多,但代价比较低。缺点:记录信息有限、每次请求都要传输Cookie
-
Session服务器
需要使用Session的时候都使用Session服务器。这种成本高,但一劳永逸。事实上是将应用服务器的状态分离,分为无状态的应用服务器和有状态的Session服务器,然后针对这两种服务器的不同特性分别设计其架构。
3.4 高可用的服务
可复用的服务和应用类似,应该也是无状态的服务,因此可以使用类似负载均衡的失效转移策略实现高可用的服务。
一些可用的策略:
-
分级管理
服务区分高优先级和低优先级,高优先级使用更好的硬件,同时在服务器部署上也要进行必要的隔离。
-
超时设置
一旦超时,转移请求
-
异步调用
适用性及广。
-
服务降级
确保必要基本功能的正常。包括拒绝服务和关闭功能。拒绝服务: 拒绝低优先级应用的调用,减少并发数目。关闭功能:关闭部分不重要的功能。
-
幂等性设计
3.5 高可用的数据
麻烦点在于数据一致性。
保证数据存储高可用的手段主要是数据备份+失效转移。数据备份:多个副本;失效转移:当某个副本不可用时,可以转移到其它副本。
争执点在于:缓存算不算数据存储服务。
3.5.1 CAP原理
高可用的数据要求包括:
-
数据持久性
-
数据可访问性
-
数据一致性
-
数据强一致
数据总是一致的,不会处于不稳定状态
-
数据用户一致
各个副本的数据可能不一致,但会通过纠错机制使得最终返回正确的数据给用户
-
数据最终一致
比较弱,中间存在不一致的时间段,最终走向一致。
-
CAP原理认为:一个提供数据服务的系统无法同时满足数据一致性(Consistency)、数据可用性(Availibility)、分区耐受性(Partition Tolerance, 系统具有网络分区的伸缩性)。一般大型数据存储服务都是集群,所以P是必须的,剩下的就是在C和A之间斟酌。
一般是偏向AP。
3.5.2 数据备份
冷备与热备。****
冷备:成本低,技术难度较低,但缺点在于不能保证数据最终一致(存在时间差)。同时也不能保证数据可用性。
数据热备:分为异步和同步两种。异步是指多份数据副本的写入操作异步完成。在回复操作成功响应时,往往只写了一份(主数据库),需要时间慢慢更新其它数据库。主从结构就用的是异步的。
同步是指多份数据副本的写入操作同时完成,即应用程序收到数据服务系统的写成功响应时,多份数据都已经写操作成功。(失败意味着可能有部分已经写入完成),服务器在这种模式下没有主从之分。
关系数据库热备机制就是主从同步机制。
3.5.3 失效转移
失效转移三部曲:
-
失效确认
一般通过心跳信号。
-
访问转移
完全对等的模式可以直接切换,存储不对等需要重新计算路由选择存储服务器。
-
数据恢复
从健康的服务器处恢复数据
3.6 高可用软件质量保证
- 网站发布
- 自动化测试
- 预发布验证
- 代码控制
- 自动化发布
- 灰度发布
3.7 网站运行监控
- 数据采集
- 用户行为日志收集
- 服务器性能监控
- 运行数据报告
- 监控管理
- 系统报警
- 失效转移
- 优雅降级
4. 伸缩性
值不需要改变网站的软硬件设计,仅仅通过改变部署的服务器数量就可以扩大或者缩小网站的服务处理能力。
只要技术上能够达到每加入一台服务器对集群的处理能力的提升都是线性关系,那么就可以了。
4.1 网站架构的伸缩性设计
一般来说,网站的伸缩性设计分成两类,一类是根据功能进行物理分离实现伸缩,一类是单一功能通过集群实现伸缩。前者是不同服务器部署不同服务,提供不同功能;后者是集群内的多台服务器部署相同服务,提供相同功能。
4.1.1 不同功能进行物理分离实现伸缩
早期通过增加服务器提高网站处理能力时,新增服务器总是从现有服务器中分离出部分功能和服务。
每次分离都会有更多服务器加入网站,使用新增的服务器处理某种特定服务。
分离主要分为两种:
-
纵向分离:
将业务处理流程上的不同部分分离部署,实现系统伸缩性。
-
横向分离:
业务分割后分离,将不同的业务模块分离部署,实现系统伸缩性。
最终的归宿:单一功能通过集群规模实现伸缩
4.2 集群的伸缩性设计
必备:负载均衡服务器——负载转发HTTP请求
负载均衡服务器的实现有两个部分:
- 根据负载均衡算法和Web服务器列表计算得到集群中一台Web服务器的地址;
- 将请求数据发送到该地址对应的Web服务器上
负载均衡的实现技术(具体怎么把一个HTTP请求转发到不同的服务器):
- HTTP重定向负载均衡
- DNS域名解析负载均衡
- 反向代理负载均衡
- IP负载均衡
- 数据链路层负载均衡
负载均衡算法(选择服务器的依据):
- 轮询(Round Robin,RR)
- 加权轮询(Weighted Round Robin,WRR)
- 随机(Random)
- 最少连接(Least Connections)
- 源地址散列(Source Hashing)——可以实现会话黏滞
4.3 分布式缓存集群的伸缩性设计
分布式缓存集群的最大难点:必须让新上线的缓存服务器对整个分布式缓存集群影响最小,也就是说新加入缓存服务器后应使整个缓存服务器集群中已经缓存的数据尽可能还被访问到,这是分布式缓存集群伸缩性设计的最主要目标。
redis vs memcached:
-
https://www.redis.com.cn/redis-vs-memcached.html
-
https://zhuanlan.zhihu.com/p/370976423
研究下redis吧,memcached有点过时了
4.3.1 Memcached分布式缓存集群的访问模型
4.3.2 分布式缓存的hash一致性算法
4.4 数据存储服务器集群的伸缩性设计
这一方面的设计和产品有哪些?
4.4.1 关系数据库集群的伸缩性设计
出了数据库主从读写分离,前面提到的业务分割模式也可以用在数据库,不同业务数据表部署在不同的数据库集群上,即数据分库。这种方式的制约条件是跨库的表不能进行join操作。
可用的有cobar——分布式关系型数据库。
4.4.2 NoSQL数据库的伸缩性设计
一般而言,NoSQL数据库产品都放弃了关系数据库的两大重要基础:以关系代数为基础的结构化查询语言(SQL)和事务一致性保证(ACID),而强化其它一些大型网站更关注的特性:高可用性和可伸缩性。
4.5 总结
良好的伸缩性设计可以走在业务发展的前面,在业务需要处理更多访问和服务之前就已经做好充足准备。
伸缩性架构需要综合考虑网站的商业模板、演化路线等等。
没有银弹。
5. 拓展性
6. 安全性
from——李智慧《大型网站技术架构——核心原理与案例分析》