第五章 万无一失:网站的高可用架构
- 网站的可用性描述网站可有效访问的特性,牵动用户的神经,大型网站的不可用事故直接影响公司形象和利益,因此非常重要
要保证一个网站永远完全可用是不可能完成的使命
- 网站可用性的度量与考核
- 网站可用性度量
业界通常用多少个9来衡量网站的可用性,如QQ的可用性是4个9,即QQ服务99.99%可用,意味着一年大约最多53分钟不可用
网站不可用时间(故障时间) = 故障修复时间点 - 故障发现(报告)时间点
网站年度可用性指标 = ((1 - 网站不可用时间) / 年度总时间) x 100% - 网站可用性度量考核
- 故障分
对网站故障进行分类加权计算故障责任
公式: 故障分 = 故障时间(分钟) x 故障权重
根据故障分类和责任划分讲故障分配给责任者(团队或个人),年末超分则影响绩效考核,具体根据不同公司会有些许不同
- 故障分
- 网站可用性度量
高可用的网站架构
- 主要手段
- 冗余备份
- 失效转移
分层架构模型
- 应用层
通过负载均衡设备和一组服务器组成集群对外提供服务,应对高并发的访问需求,负载均衡设备通过心跳监测等手段进行监控、剔除和转移,从而实现高可用 - 服务层
类似于应用层,分布式服务应用框架会在应用层客户端程序中实现负载均衡,并通过服务注册中心对提供服务的服务器进行心跳检测、剔除和转移 - 数据层
通过写入数据时进行数据同步复制,实现数据冗余备份,宕机时应用程序自动切换访问到备份数据服务器
复杂大型架构划分粒度更细,结构更加复杂,但通常还是可以划分到以上三层中
- 应用层
- 升级问题
网站升级频率一般非常高,需要考虑网站升级发布引起的宕机,不能因为系统可以接受偶尔的停机故障就降低可用性设计的标准
- 主要手段
- 高可用的应用
- 无状态
应用服务器不保存业务的上下文信息,请求提交到任意服务器,处理结果完全一样 - 通过负载均衡设备进行无状态服务的失效转移
注意: 即使某个应用访问量非常少,要想保证服务高可用,也必须至少部署两台服务器,使用负载均衡技术构建小型集群 - 应用服务器的Session管理
- Session复制
应用服务器开启Web容器的Session复制功能,服务器之间同步Session对象,每台服务器都保存所有用户的Session信息,任何一台机器宕机都不会导致Session丢失,服务器使用Session只需从本机获取
缺点:集群规模较大时过于占用服务器和网络的资源,大量用户访问甚至会出现内存不够Session使用的情况 - Session绑定
利用源地址Hash算法实现,总是将同一IP请求分发到同一服务器
缺点: 不符合高可用的需求,一旦某台服务器宕机,其上Session全部不复存在,用户请求即使切换也无法继续完成业务处理 - 利用Cookie记录Session
将Session返回给浏览器,每次通过Cookie携带
缺点:Cookie大小限制,每次携带Cookie影响性能,用户关闭Cookie网站访问就不正常 - Session服务器
独立部署的Session服务器(集群)统一管理Session,每次访问Session时都访问Session服务器。
将应用服务器状态分离,分为无状态应用服务器和有状态Session服务器,然后分别设计其架构
有状态Session服务器通常是利用分布式缓存、数据库等实现,如有单点登录、用户服务等功能则需要开发专门的Session服务管理平台
- Session复制
- 无状态
- 高可用的服务
- 分级管理
运维上将服务器进行分级管理,核心应用和服务优先使用更好的硬件,在运维响应速度上也格外迅速,比如订单支付优先级高于评价等 - 超时设置
为防止宕机、死锁等原因导致失去响应,给服务调用设置超时时间,一旦超时,通信框架抛出异常,应用程序根据服务调度策略,可继续重试或者请求转移其他服务器 - 异步调用
应用对服务的调用通过消息队列等异步方式完成,避免一个服务请求失败导致整个应用请求失败,提高响应的速度,比如用户注册需要使用的邮件服务
注意:必须确认服务调用成功才能进行下一步操作的应用不适合使用异步调用 - 服务降级
网站高峰期,大量并发导致性能下降甚至宕机,为了核心应用和功能正常运行,需要进行降级 - 拒绝服务
拒绝优先级低应用的调用,减少服务调用并发数,确保核心应用正常使用;或者随机拒绝部门请求调用,节约资源,让另一部分请求成功,避免全死的悲剧 - 关闭功能
关闭部分不重要的服务,或者服务内部关闭部分不重要的功能,节约系统开销,让出资源,保证核心服务顺利完成 - 幂等性设计
应用调用服务因网络故障没收到结果就会认为服务调用失败而重试,因此服务重复调用是无法避免的,需要在服务层保证服务重复调用和调用一次的结果相同,即服务具有幂等性,特别注意如交易这种业务的有效性校验
- 分级管理
高可用的数据
CAP原理
高可用的数据具有如下含义:- 数据持久性
写入数据时需要写入持久性存储,并且需要有一个或多个副本,保证灾害发生时数据不会丢失 - 数据可访问性
数据存储设备损坏后的切换过程如果不能很快完成(最终用户没有感知),或者需要停止终端用户访问数据,那么这段时间是不可访问的 - 数据一致性
所有应用程序访问能得到相同的数据
原理:一个提供数据服务的存储系统无法同时满足数据一致性(Consistency)、数据可用性(Availibility)、分区耐受性(Partition Tolerance)
互联网公司一般选择强化可用性(A)和伸缩性(P),而某种程度上放弃一致性(C)数据一致性分为:
- 数据强一致
各个副本中的数据总是一致的 - 数据用户一致
各个副本中数据可能不一致,但是终端用户访问时通过纠错和校验机制,可以确定一个一致的且正确的数据返回给用户 - 数据最终一致
各个副本中数据可能不一致,终端用户访问的数据可能也不一致,但系统经过一段时间自我恢复和修正,数据最终会达到一致
网站通常会综合各方面情况是存储系统达到用户一致
- 数据持久性
数据备份
- 冷备
定期备份,简单廉价,成本和技术较低
缺点: 不能保证数据最终一致,会丢失一部分数据;不能保证数据可用性,恢复数据时间长 - 热备
- 异步热备
存储服务器分贝主存储(Master)和从存储(Slave),应用程序正常情况下只连接主存储服务器进行写入,存储服务器写操作代理将数据写入本机存储系统后立即返回,然后异步线程将写操作数据同步到从存储服务器 - 同步热备
多份数据副本的写入操作同步完成再返回,会有应用程序收到数据写操作失败的响应时,已有部分或全部副本写成功(网络或系统故障,无法返回成功)的情况,需要做处理
为了提高性能,应用程序客户端会并发向多个存储服务器写入数据,等待所有操作返回成功响应,再通知应用程序写操作成功
存储服务器没有主从之分,完全对等,方便管理和维护,并发写入意味着总写操作延迟是响应最慢的那台服务器的响应延迟,因此跟异步热备速度差不多
- 异步热备
关系数据库热备机制就是Master-Slave同步机制,解决了数据备份问题,还改善了数据库系统的性能,通常读写分离,写Master读Slave
- 冷备
- 失效转移
- 失效确认
应用客户端访问存储服务器失败生成失效报告并告知控制中心,然后控制中心发送心跳检测进行确认,以免错误判断 - 访问转移
如果是完全对等的存储服务器,则直接切换到对等服务器上;如果是不对等的存储服务器,需要重新计算路由并选择 - 数据恢复
存储服务器宕机导致数据存储的副本数目减少,必须将副本数目恢复到系统设定的值,否则再有服务器宕机,可能无法访问转移,数据永远丢失
- 失效确认
高可用网站的软件质量保证
- 网站发布
一次提前预知的宕机,发布过程中每次关闭的服务器都是集群中的一小部分,在发布完成后可立即访问,因此整个过程不影响用户使用 - 自动化测试
系统功能即使小幅增加,也需要全面回归测试,还需要测试各种浏览器的兼容性。如果使用人工测试,成本、时间和测试覆盖率都难以接受。目前大部分网站采用Web自动化测试技术,使用自动测试工具或脚本完成测试。目前比较流行的有ThoughtWorks开发的Selenium - 预发布验证
测试环境和线上环境并不相同,特别是应用需要依赖的其他服务,如数据库、缓存、公共业务服务等,以及一些第三方服务,如电信短信网关、银行网银接口等,因此部署后经常会出问题
预发布服务器和线上正式服务的唯一区别就是没有配置在负载均衡服务器上,外部用户无法访问,因此使用预发布服务器验证后,发布到正式环境基本可以确保正式服务器部署也没问题
注意:预发布验证会导致真实数据库终会有少量测试数据,需处理
网站应用强调的一个处理错误的理念是快速失败,启动时发现问题抛出异常并立刻停止启动进行排查错误,而不是启动后执行一些错误的操作
- 代码控制
- SVN
- 主干开发,分支发布
主干反应目前整个应用的状态,一目了然,便于管理控制,也利于持续集成,但如果有不同发布时间的项目在主干上,不能灵活发布项目 - 分支开发,主干发布
各个分支独立进行互不干扰,可以使不同发布周期的开发在同一应用中进行,不同周期项目可以灵活合并后进行发布
- 主干开发,分支发布
- Git
Git对分布式开发、分支开发支持更好,但学习成本较高,缺乏最佳实践和使用规范,但前途无量啊
- SVN
- 自动化发布
人为干预越少,自动化程度越高,引入故障的可能性就越小
规则驱动流程:自动构造代码分支,进行代码合并,执行发布脚本等 - 灰度发布
集群规模庞大,分成若干部分,每天发布一部分服务器,观察稳定后第二天继续发布,发现问题可及时回滚
灰度发布也用于用户测试,可监控用户操作行为,收集用户体验报告,比较两个版本的满意度,此称为AB测试
- 网站发布
网站运行监控
不允许没有监控的系统上线- 监控数据采集
用户行为日志收集
- 服务器端日志收集
Apache等几乎所有Web服务器具备日志记录功能,开启即可
缺点:可能出现信息失真,比如IP;无法识别访问路径 客户端浏览器日志收集
页面嵌入专门的JavaScript脚本,收集更精确
缺点:比较麻烦目前很多网站逐步开发基于实时计算框架Storm的日志统计和分析工具
- 服务器端日志收集
- 服务器性能监控
收集服务器的性能指标,如系统Load、内存占用、磁盘IO、网络IO等,即使判断,防范于未然,运维工程师可以合理安排集群规模,架构师及时改善系统性能和调整伸缩性策略
目前用的比较广泛的开源性能监控工具是Ganglia,支持大规模服务器集群和图形方式展示 - 运行数据报告
监控一些与具体业务场景相关的技术和业务指标,比如缓存命中率、平均响应延迟、每分钟发送邮件数、待处理的任务总数等
服务器性能监控由网站运维人员在初始化系统时统一部署,应用程序开发时不用关心
运行数据需要在具体程序中采集并报告,汇总后统一显示,因此需要在代码中处理数据采集的逻辑- 监控管理
- 系统报警
监控指标超过阈值,系统自动向相关人员进行报警(邮件、短信、语音等) - 失效转移
监控系统发现故障时主动通知应用进行失效转移,而非访问失败后再转移 - 自动优雅降级
根据监控参数判断负载情况,自动卸载低负载应用部分服务器,重新安装启动部分高负载应用,使应用负载总体均衡,若果所有负载都很高,而且压力还在继续增加,就自动关闭部分非重要功能,保证核心功能正常运行
- 网站可用性的度量与考核