高可用架构
1. 网站可用性的度量
网站不可用也被称作网站故障,业界通常用多个 9 来衡量网站的可用性。如 QQ 的可用性为 4 个 9,即 99.99% 可用。
1 | 网站不可用时间 = 故障修复时间点 - 故障发现时间点 |
一般来说:
- 2 个 9 是基本可用,一年不可用时间小于 88 小时;
- 3 个 9 是较高可用,一年不可用时间小于 9 小时;
- 4 个 9 是具有自动恢复能力的高可用,一年不可用时间小于 55 分钟;
- 5 个 9 是极高可用,一年不可用时间小于 5 分钟。
2. 高可用的系统架构
通常,企业级应用系统为提高系统可用性,会采用较昂贵的软硬件设备,当然这样的设备也比较稳定。
互联网公司或一些初创型公司基于成本考虑,更多采用 PC 级软硬件设备,节约成本所付出的代价就是设备较为不稳定。服务器一年中出现几次宕机,高强度读写磁盘导致磁盘损坏等事件实属正常。
综上,硬件出现故障应视为必然的,而高可用的系统架构设计目标就是要保证当出现硬件故障时,服务依然可用,数据依然能够保存并被访问。
实现高可用的系统架构的主要手段是数据和服务的冗余备份及失效转移,一旦某些服务器宕机,就将服务切换到其他可用的服务器上;如果磁盘损坏,则从备份的磁盘读取数据。
3. 高可用的应用
应用层主要处理网站应用的业务逻辑,一个显著的特点是应用的 无状态 性。
所谓的 无状态 的应用是指应用服务器不保存业务的上下文信息,而仅根据每次请求提交的数据进行相应的业务逻辑处理,多个服务实例之间完全对等,请求提交到任意服务器,处理结果都是完全一样的。
3.1. 通过负载均衡进行无状态服务的失效转移
无状态的应用实现高可用架构十分简单,由于服务器不保存请求状态,那么所有服务器完全对等,在任意节点执行同样的请求,结果总是一致的。这种情况下,最简单的高可用方案就是使用负载均衡。
负载均衡,顾名思义,主要使用在业务量和数据量较高的情况下,当单台服务器不足以承担所有的负载压力时,通过负载均衡手段,将流量和数据分摊到一个集群组成的多台服务器上,以提高整体的负载处理能力。
3.2. 应用服务器集群的 Session 管理
应用服务器的高可用架构设计主要基于服务无状态这一特性。事实上,业务总是有状态的,如购物车记录用户的购买信息;用户的登录状态;最新发布的消息等等。
Web 应用中将这些多次请求修改使用的上下文对象称作会话。单机情况下,Session 可由部署在服务器上的 Web 容器管理。
而在集群环境下,Session 管理有以下手段:
3.2.1. Session 复制
Session 复制是指应用服务器开启 Web 容器的 Session 复制功能,在集群中的几台服务器之间同步 Session 对象,使得每台服务器上都保存所有用户的 Session 信息。
这种方案很简单但不可取。因为当集群规模较大时,集群服务间需要大量的通信来进行 Session 复制,占用服务器和网络的大量资源。
3.2.2. Session 绑定
Session 绑定可以利用负载均衡的源地址 Hash 算法实现,负载均衡服务器总是将来源于同一 IP 的请求分发到同一台服务器上。这样在整个会话期间,用户所有的请求都在同一台服务器上处理,即 Session 绑定到某台特定服务器上。这种方法又被称作会话黏滞。
但是这种策略不符合系统高可用的需求,因为一旦某台服务器宕机,那么该机器上的 Session 也就不复存在了。
3.2.3. 利用 Cookie 记录 Session
可以将 Session 记录在客户端(浏览器 Cookie),每次请求服务器时,将 Session 放在请求中发送给服务器,服务器处理完请求后再将修改过的 Session 响应给客户端。
这种策略的缺点是:
- Cookie 有大小限制,能记录的信息有限;
- 每次请求响应都需要传输 Cookie,影响性能;
- 如果用户关闭 Cookie,访问就不能工作。
3.2.4. Session 服务器
利用独立部署的 Session 服务器(集群)统一管理 Session,应用服务器每次读写 Session 时,都访问 Session 服务器。
实现 Session 服务器的一种简单方法时:利用分布式缓存、数据库等,在此基础上进行包装,使其符合 Session 的存储和访问要求。如果业务对 Session 管理有较高要求,如利用 Session 服务集成单点登录(SSO)、用户服务等功能,则需要开发独立的 Session 服务管理平台。
4. 高可用的服务
高可用的服务策略:
- 分级管理
- 将服务根据业务重要性进行分级管理,核心应用和服务优先使用更好的硬件,在运维响应速度上也格外迅速。
- 在服务部署上进行必要的隔离,避免故障的连锁反应。低优先级的服务通过启动不同的线程或部署在不同的虚拟机上进行隔离,而高优先级的服务则需要部署在不同的物理机上,核心服务和数据甚至要部署在不同地域的数据中心。
- 超时设置 - 由于服务器宕机、线程死锁等原因,可能导致应用程序对服务端的调用失去响应。所以有必要引入超时机制,一旦调用超时,服务化框架抛出异常,应用程序根据服务调度策略,选择重试或请求转移到其他机器上。
- 异步调用 - 对于需要即时响应的业务,应用在调用服务时可以通过消息队列等异步方式完成,避免一个服务失败导致整个应用请求失败的情况。当然不是所有服务调用都可以异步调用,对于获取用户信息这类调用,采用异步方式会延长响应时间,得不偿失;此外,对于那些必须确认服务调用才能继续下一步操作的应用也不适宜食用异步调用。
- 服务降级 - 网站访问高峰期,服务可能因为大量并发调用而性能下降,严重时可能会导致宕机。为了保证核心功能的正常运行,需要对服务进行降级。降级有两种手段:
- 拒绝服务 - 拒绝低优先级应用的调用,减少服务调用并发数,确保核心应用正常使用。或者随机拒绝部分调用,节约资源,避免要死大家一起死的惨剧。
- 关闭服务 - 关闭部分不重要的服务,或者服务内部关闭部分不重要的功能,以节约资源。
- 幂等性设计 - 为了避免服务重复调用,可以通过设置编号的方式进行服务调用有效性校验,有效的操作才能继续执行。
5. 高可用的数据
5.1. CAP 原理
分布式系统不可能同时满足一致性(C:Consistency)、可用性(A:Availability)和分区容忍性(P:Partition Tolerance),最多只能同时满足其中两项。
5.1.1. 可用性
可用性指分布式系统在面对各种异常时可以提供正常服务的能力。可以用系统可用时间占总时间的比值来衡量,4 个 9 的可用性表示系统 99.99% 的时间是可用的。
在可用性条件下,系统提供的服务一直处于可用的状态,对于用户的每一个操作请求总是能够在有限的时间内返回结果。
5.1.2. 分区容忍性
网络分区指分布式系统中的节点被划分为多个区域,每个区域内部可以通信,但是区域之间无法通信。
在分区容忍性条件下,分布式系统在遇到任何网络分区故障的时候,仍然需要能对外提供一致性和可用性的服务,除非是整个网络环境都发生了故障。
5.1.3. 一致性
一致性指的是多个数据副本是否能保持一致的特性。
在一致性的条件下,系统在执行数据更新操作之后能够从一致性状态转移到另一个一致性状态。
数据一致性又可以分为以下几点:
- 强一致性 - 数据更新操作结果和操作响应总是一致的,即操作响应通知更新失败,那么数据一定没有被更新,而不是处于不确定状态。
- 最终一致性 - 即物理存储的数据可能是不一致的,终端用户访问到的数据可能也是不一致的,但系统经过一段时间的自我修复和修正,数据最终会达到一致。
5.1.4. 权衡
在分布式系统中,分区容忍性必不可少,因为需要总是假设网络是不可靠的。因此,CAP 理论实际在是要在可用性和一致性之间做权衡。
可用性和一致性往往是冲突的,很难都使它们同时满足。在多个节点之间进行数据同步时,
- 为了保证一致性(CP),就需要让所有节点下线成为不可用的状态,等待同步完成;
- 为了保证可用性(AP),在同步过程中允许读取所有节点的数据,但是数据可能不一致。
5.2. 数据备份
- 冷备份 - 定期将数据复制到某种存储介质。
- 热备份
- 异步热备方式 - 异步热备方式是指多份数据副本的写入操作异步完成,应用程序收到数据服务系统的写操作成功响应时,只写成功了一份,存储系统将会异步地写其他副本。
- 同步热备方式 - 同步热备方式是指多份数据副本的写入操作同步完成,即应用程序收到数据服务系统的写成功响应时,多份数据都已经写操作成功。但是当应用程序收到数据写操作失败的响应式,可能有部分副本或者全部副本都已经写入成功了(因为网络或者系统故障,无法返回操作成功的响应)。
5.3. 失效转移
5.3.1. 失效确认
判断服务器宕机的手段有两种:心跳检测和访问失败报告。
对于应用程序的访问失败报告,控制中心还需要再一次发送心跳检测进行确认,以免错误判断服务器宕机。因为一旦进行数据访问的失效转移,意味着数据存储多份副本不一致,需要进行后续一系列的复杂动作。
5.3.2. 访问转移
确认某台数据服务器宕机后,就需要将数据读写访问重新路由到其他服务器上。对于完全对等存储的服务器,当其中一台宕机后,应用程序根据配置直接切换到对等服务器上。如果存储不对等,就需要重新计算路由,选择存储服务器。
5.3.3. 数据恢复
因为某台服务器宕机,所以数据存储的副本数目会减少,必须将副本的数目恢复到系统设定的值,否则,再有服务器宕机时,就可能出现无法访问转移,数据永久丢失的情况。因此系统需要从健康的服务器复制数据,将数据副本数目恢复到设定值。
6. 高可用的软件质量保证
高可用的软件质量保证的手段:
- 自动化发布
- 自动化测试
- 预发布验证
- 代码控制
- 灰度发布
7. 系统监控
不允许没有监控的系统上线。
- 监控数据采集
- 用户行为日志收集
- 服务端日志收集 - Apache、Nginx 等几乎所有 Web 服务器都具备日志记录功能,只要开启日志记录即可。如果是服务器比较多,需要集中采集日志,通常会使用 Elastic 来进行收集。
- 客户端日志收集 - 利用页面嵌入专门的 JavaScript 脚本可以收集用户真实的操作行为。
- 日志分析 - 可以利用 ElasticSearch 做语义分析及搜索;利用实时计算框架 Storm、Flink 等开发日志统计与分析工具。
- 服务器性能监控 - 收集服务器性能指标,如系统负载、内存占用、CPU 占用、磁盘 IO、网络 IO 等。常用的监控工具有:Apache SkyWalking 等。
- 运行数据报告 - 应该监控一些与具体业务场景相关的技术和业务指标,如:缓存命中率、平均响应时延、TPS、QPS 等。
- 用户行为日志收集
- 监控管理
- 系统报警 - 设置阈值。当达到阈值,及时触发告警(短信、邮件、通信工具均可),通过及时判断状况,防患于未然。
- 失效转移 - 监控系统可以在发现故障的情况下主动通知应用进行失效转移。
- 自动优雅降级
- 优雅降级是为了应付突然爆发的访问高峰,主动关闭部分功能,释放部分资源,以保证核心功能的优先访问。
- 系统在监控管理基础之上实现自动优雅降级,是柔性架构的理想状态。