第四章
4 瞬时响应:网站的高性能架构
4.1 网站性能测试
不同视角下的网站性能
1 | 1. 用户视角:用户在浏览器上直观感受到的网站相应速度,包括用户计算机和网站服务器通信的速度、网站服务器处理的速度、用户计算机浏览器构造请求解析响应数据的速度。 |
性能指标:响应时间,并发数,吞吐量
性能测试,细分为:
1 | a) 性能测试:以系统设计初期规划的性能指标为预期目标,不断施加压力(增加并发请求),验证系统在资源可接受范围,可否达到预期。 |
性能测试曲线:横坐标为消耗的系统资源,纵坐标为吞吐量。a~b为网站日常运行区间,c为系统最大负载点,d为系统崩溃点。
访问等待时间
性能测试报告
性能优化策略
性能分析
检查请求处理的各个环节的日志,分析哪个环节响应时间不合理、超过预期。
检查监控数据,分析影响性能的主要因素是内存、磁盘、网络、还是CPU,是代码问题还是架构设计不合理,或者系统资源确实不足。性能优化
Web前端性能优化
应用服务器性能优化
存储服务器性能优化
4.2 Web前端性能优化
浏览器访问优化
1 | 1. 减少HTTP请求:合并CSS、合并JavaScript、合并图片。 |
CDN加速
反向代理
4.3 应用服务器性能优化
分布式缓存
1 | 1. 网站性能优化第一定律:优先考虑使用缓存优化性能。 |
注意事项。
1 | a) 频繁修改的数据:如果缓存频繁修改的数据,会造成写入缓存后来不及读取已失效。一般数据读写比应在2:1以上,甚至更高。 |
异步操作
使用原则就是,任何可以晚点做的事情都应该晚点再做。
在使用消息队列进行业务异步处理后,需要适当修改业务流程进行配合,如订单提交后,订单数据写入消息队列,不能立即返回用户订单提交成功,需要在消息队列的订单消费者进程真正处理完该订单,甚至商品出库后,再通过电子邮件或 SMS消息通知用户订单成功,以免交易纠纷。
使用集群
代码优化
- 多线程
1
2a) 目的:利用多线程IO阻塞与执行交替进行,最大限度利用CPU资源;多线程最大限度利用多核CPU。
b) Web容器线程数设置:如果都是CPU计算型任务,则线程数最多不超过CPU内核数(更多线程CPU来不及调度);如果都是等待磁盘IO、网络IO的任务,则多启动线程有助于提高任务并发度,提高吞吐能力。 - 资源复用:单例(Singleton)、对象池(Object Pool)。
- 数据结构。
- 垃圾回收:即优化JVM。
4.4 存储性能优化(不常用,略)
机械硬盘 VS 固态硬盘
B+树 VS LSM树
RAID VS HDFS
4.5 小结
5 万无一失:网站的高可用架构
5.1 网站可用性的度量与考核
度量
1 | 1. 业界通常用多少个9来衡量网站可用性。 |
考核
略
5.2 高可用的网站架构
实现高可用架构主要手段:数据和服务的冗余备份及失效转移。
应用层高可用:通过负载均衡设备将一组服务器组成一个集群对外处理高并发请求,负载均衡设备通过心跳检测等手段监控到应用服务器不可用时,将其从集群列表剔除,请求分发到集群其他可用服务器上。
服务层高可用:也是通过集群实现高可用。服务层被应用层通过分布式服务调用框架访问,分布式服务调用框架在应用层客户端中实现负载均衡,服务注册中心获取服务层服务器心跳检测,发现不可用服务器,立即通知客户端修改服务层访问列表,剔除不可用服务器(说的就是Dubbo)。
数据层高可用:比较特殊,数据服务器存储了数据。数据写入时同步复制数据到多台服务器上,实现数据冗余备份;数据服务器宕机时,数据访问切换到备份数据服务器上。
网站升级发布可能引起故障。
5.3 高可用的应用
通过负载均衡进行无状态服务失效转移
无状态应用:应用服务器不保存业务的上下文信息,而仅根据每次请求提交的数据处理业务逻辑,多台服务器之间完全对等,请求提交到任意服务器结果一样。是应用层高可用的基础。
应用服务器集群的Session管理
事实上业务总是有状态的(Session),负载均衡集群环境下,负载均衡服务器可能会将请求分发到集群任何依他应用服务器上,所以每次请求获取正确的Session要比单机复杂。几种手段:
1 | 1. Session复制:集群各台服务器间同步Session对象,每台服务器都保存所有用户的Session信息。服务器内存无法保存大量Session,不适合大型网站。 |
5.4 高可用的服务
- 分级管理。
1
2a) 核心应用和服务优先使用更好的硬件和更快的运维响应速度。
b) 部署隔离,避免故障连锁反应:低优先级服务启动不同线程或部署在不同虚拟机上隔离;高优先级服务部署在不同物理机上;核心服务和数据甚至部署在不同地域的数据中心。 - 超时设置:在应用程序设置服务调用超时时间,超时后通信框架抛出异常,避免因服务器宕机、线程死锁导致应用程序对服务端调用失去响应,进而用户请求长时间得不到响应,同时占用应用程序资源。
- 异步调用:前面章节已说明,不再赘述。
- 服务降级:有两种手段。
1
2a) 拒绝服务:拒绝低优先级应用的调用,减少并发数,确保核心应用正常调用;随机拒绝部分请求调用,让另一部分请求成功,避免大家一起死的餐具。
b) 关闭服务:关闭部分不重要服务或服务内部关闭部分不重要功能,节约开销。 - 幂等性设计:应用层只要未收到调用成功的响应,都认为调用服务失败,并重试服务调用,因此服务层必须保证服务重复调用和调用一次的结果相同,即服务具有幂等性。
5.5 高可用的数据
CAP原理
- 数据高可用含义。
1
2
3a) 数据持久性:在各种情况下都不会出现数据丢失问题。
b) 数据可访问性:多数据副本分别存放在不同存储设备情况下,失效转移能很快完成(终端用户几乎没有感知)。
c) 数据一致性:多数据副本情况下,各副本之间数据一致。 - CAP原理:一个提供数据服务的存储系统无法同时满足数据一致性(Consistency)、数据可用性(Availability)、分区耐受性(Partition Tolerance)这三个条件。
- 大型网站实践:通常选择强化分布式存储系统的可用性(A)和伸缩性(P),而在某种程度上放弃一致性(C)。一般数据不一致出现在系统高并发写操作或集群状态不稳定(故障恢复、集群扩容等)时,应用系统要对分布式数据处理系统的数据不一致性有了解并进行某种意义上的补偿和纠错,以保证最终一致性。
数据备份
- 冷备。
1
2
3a) 优点:简单、廉价,成本和技术难度都较低。
b) 缺点:无法保证数据一致性(备份设备中的数据比系统中的数据陈旧)。
c) 现状:作为传统的数据保护手段依然在运维中使用。 - 热备。
1
2a) 异步热备:多份数据副本的写入操作异步完成,即应用程序收到数据服务系统的写操作成功响应时,只写成功了一份,存储系统将异步地写其他副本(该过程可能失败)。
b) 同步热备:多份数据副本的写入操作同步完成,即应用程序收到数据服务系统的写成功响应时,多份数据都已经写操作成功。 - 同步热备优化:应用程序客户端并发向多个存储服务器同时写入数据,所有写操作成功响应后,再通知应用程序成功。优点:存储服务器无主从之分,完全对等,便于管理维护;并发写操作意味着多份数据的总写操作延时是响应最慢的那台存储服务响应。
- 实际:通常使用读写分离,写操作只访问Master数据库,读操作只访问Slave数据库。
失效转移
- 失效确认:有心跳检测和应用程序访问失败报告两种手段。对于后者,控制中心还要再一次发送心跳检测确认,以免错误判断服务器宕机。
- 访问转移:将数据读写访问重新路由到其他服务器上。
- 数据恢复:数据副本数目已减少,必须将副本数目恢复到系统设定的值,否则再有宕机可能无法访问转移(所有副本服务器宕机)。
5.6 高可用网站的软件质量保证
自动化测试
预发布验证
代码控制
自动化发布
灰度发布
5.7 网站运行监控
监控数据采集
- 用户行为日志收集:用户在浏览器上的所有操作及其操作环境,包括操作系统、浏览器版本、IP地址、页面访问路径、网页停留时间等,对统计网站PV/UV、分析用户行为、优化网站设计、个性营销与推荐非常重要。
- 服务器性能监控:收集服务器性能指标,如系统Load、内存占用、磁盘IO、网络IO等。
监控管理
- 系统预警:超过预设阀值意味着可能出现故障,此时通过邮件、短信等方式报警。
- 失效转移:除应用程序访问时失效转移,监控系统在发现故障时主动通知应用失效转移。
- 自动降级:关闭次要服务,保证核心服务。
5.8 小结
6 永无止境:网站的伸缩性架构
6.1 网站架构的伸缩性设计
不同功能物理分离实现伸缩:主要是分层、分割后的业务和模块独立部署
1 | 纵向分离,将业务处理上的不同部分分离部署; |
单一功能通过集群实现伸缩:将单一服务集群部署提供服务
6.2 应用服务器集群的伸缩性设计
主要是通过负载均衡实现集群的伸缩。
负载均衡技术:
1 | http重定向 |
负载均衡算法:
1 | 1. 轮询(Round Robin,RR):所有请求依次分发到每台服务器,适合所有服务器硬件都相同的场景。 |
6.3 分布式缓存集群的伸缩性设计
- 分布式缓存集群特点:集群中各服务器数据不同,缓存访问请求不可以在任意一台处理,必须先找到有缓存数据的服务器才能访问。
- 分布式缓存集群访问原理:以写缓存Memcached为例,应用程序输入数据<’BEIJING’,DATA>,API将KEY(‘BEIJING’)输入路由算法模块,路由算法根据KEY和集群服务器列表计算得到一台服务器编号NODE1和IP地址、端口;API调用通信模块将数据写入服务器NODE1。
- 分布式缓存的一致性Hash算法:可解决伸缩性问题,但算法介绍Memcached且复杂,可能会使用Redis代替,以后再看。
6.4 数据存储服务器集群的伸缩性设计
关系数据库集群的伸缩性设计
- 主从复制:利用关系数据库数据复制功能,进行简单伸缩。
- 分库:不同业务数据表部署在不同数据库集群上。制约条件是跨库不能join操作。
- 分片:对某些单表数据量大的表(如Facebook用户表、淘宝商品表),将一张表拆分存储在多个数据库。
1
2
3a) 比较成熟的支持数据分片的开源分布式关系数据库产品:Amoeba、Cobar。
b) 分布式关系数据库特点:限制了关系数据库某些功能;海量数据压力不得不利用分布式关系数据库伸缩。
c) 分布式关系数据库注意:避免事务或利用事务补偿机制代替数据库事务;分解数据访问逻辑避免join操作。
NoSQL数据库集群的伸缩性设计
NoSQL特点:放弃了关系数据库的以关系代数为基础的结构化查询语言(SQL)和事务一致性保证(ACID),而强化大型网站关注的高可用性和可伸缩性。
6.5 小结
7 随需应变:网站的可扩展架构
扩展性与伸缩性
- 扩展性(Extensibility):对现有系统影响最小的情况下,系统功能可持续扩展或提升的能力。
- 伸缩性(Scalability):系统能够通过增加(减少)自身资源规模的方式增强(减少)自己计算处理事务的能力。
构建可扩展的网站架构
- 设计网站可扩展架构的核心思想是模块化,并在此基础上降低模块间的耦合性,提高模块复用性。
- 模块化的重要手段:分层和分割,分层、分割为若干个低耦合的独立组件模块(模块可分布式部署,从物理上分离模块间耦合),各模块以消息传递及依赖调用方式聚合成完整系统。
利用分布式消息队列降低系统耦合性
- 事件驱动架构(Event Driven Architecture):通过在低耦合的模块之间传输事件消息,以保持模块的松散耦合,并借助事件消息的通信完成模块间合作。典型的EDA架构就是生产者消费者模式。大型网站最常见是分布式消息队列,利用发布/订阅模式工作。
- 分布式消息队列。
1
2
3
4a) 原理:前面章节已说明,不再赘述。
b) 伸缩性:新服务器加入消息队列集群事,修改生产者服务器的消息队列服务器列表即可。
c) 可用性:为避免消费者进程处理缓慢、消息队列服务器内存不足等问题,如果内存队列已满,消息会被写入磁盘;为避免消息队列服务器宕机,生产者服务器会保存消息直至消息真正被消费者服务器处理后才删除,如果消息队列服务器宕机,生产者服务器会选择分布式消息队列集群中其他服务器发送。
d) 开源Apache ActiveMQ实现了可用性、伸缩性、数据一致性、性能和可管理性等。
利用分布式服务打造可复用的业务平台
- 纵向拆分:将一个大应用拆分为多个小应用,如果新增业务较为独立,那么直接部署为一个独立的Web应用。
- 横向拆分:将复用的业务拆分,独立部署为分布式服务,新增业务只需要调用这些分布式服务,无需依赖具体模块代码。
大型网站分布式服务的需求与特点
1 | a) 注册与发现; |
开源分布式服务框架:阿里巴巴Dubbo、Facebook Thrift。
8 固若金汤:网站的安全架构(略)
架构设计和高并发系列
读书_大型网站技术架构01_李智慧
读书_大型网站技术架构02_李智慧
读书_大型网站技术架构03_李智慧
读书_高并发设计40问之一基础
读书_高并发设计40问之二数据库
读书_高并发设计40问之三缓存
读书_高并发设计40问之四消息队列
读书_高并发设计40问之五分布式服务
读书_w3c架构师01通用设计与方法论
读书_w3c架构师02典型架构实践
读书_w3c架构师03数据库与缓存
分布式事务
高并发之缓存
高并发之降级
高并发之限流
数据库_读写分离
消息队列_01消息队列入门
消息队列_02rabbitMQ入门
消息队列_03rabbitMQ安装和使用