大话云计算:从云起源到智能云未来
上QQ阅读APP看书,第一时间看更新

第3章 打破常规的服务方式

3.1 稳定性——N个9的SLA

任何服务的提供商都需要一项指标来帮助它们管理客户的期望,并定义针对不同事件所需要担负的责任。例如,如果家里停电,电力公司可能会根据停电时长给予客户补贴。在云计算平台上,如何定义停机或性能问题的严重性,如何为客户提供可用性保障,并且让客户可以安心使用,这些细则都是服务协议及合同所需要详细描述的。

SLA(服务级别协议)通常是服务提供商与客户签订的两项基本协议之一,它起源于20世纪80年代末IT外包流行的时期。当时,SLA是管理这种外包关系的核心机制之一,它设定了对服务提供商的绩效期望,并规定了对未达成目标的处罚方式,在有些情况下,甚至还规定了超出目标的奖金。

本节会详细介绍SLA中的各个细则组成部分,帮助读者了解如何对一个云平台从服务协议上进行准确评估。

3.1.1 评估稳定性的SLA

稳定性,在多数场合也称为可用性,是一个服务的多个质量指标的集合。一个服务作为一个整体,在工作时要面对组成它的各个子部件出现的风险,这些子部件对整体服务的影响,取决于部件提供的功能、部件在系统中的可替代性,以及风险在系统中传递的方式三方面。

在众多指标及指定时间跨度中,在线时间(up time)占比是最重要的一个。

在与下游用户的交互中,服务的提供方应该给出自己服务的稳定性指标,并在服务存继期间维护该指标。例如,如果Azure承诺自己的应用程序网关在线时间占比为99.99%,或者简称4个9,那么它一年内的下线时间不应该超过52.56min(365×24×60×(1-0.9999))。一些科技公司通常把前面计算得到的下线时间作为开发团队或者运维团队的绩效指标(KPI),或者更贴切地说“下线预算”。

云服务对于自己每一种服务的在线时间占比都会有清晰的承诺,比如Azure对于自己的应用程序网关服务的承诺如图3-1所示,承诺99.95%的在线率。

图3-1 Azure的应用程序网关服务承诺

3.1.2 稳定性的计算方式

稳定性可以以定量的方式计算。通过一个系统内各个服务相互影响的情况分析,可将计算稳定性的方式分为两种:一种是上下游关系的不同服务;另一种是并行的可相互替代的服务实例。一个系统总体的稳定性,可以基于各个子服务的稳定性数据和它们相互之间的关系计算出来。

1.上下游关系的不同服务

两个服务以上下游的关系存在,即一个服务单向地依赖另一个服务的内容,这里可以借用“串联”的概念来描述这种关系。比如一个博客程序和它依赖的数据库、一个微信小程序和微信平台,以及一个进程和运行它的操作系统。此时,博客程序、微信小程序和进程处于下游,而数据库、微信平台和操作系统处于上游。在一般的设计中,下游的可靠性与上游的可靠性正相关。

这里用个简化的模型来演示如何计算综合稳定性。假设一个博客服务自身程序在外部依赖正常工作的情况下可以保证99.99%的在线时间占比,它所依赖的数据库(如果是集群,那么就作为一个整体看待)承诺的在线时间占比为99.99%,那么此博客服务的综合稳定性,或者说,它能对外承诺的在线时间占比应该小于或等于

99.99%×99.99%≈99.98%

从上面的例子可以看到,两个承诺99.99%在线时间占比的服务串联在一起还能提供99.98%在线时间占比,最终的结果似乎还可以接受。但是随着串联层数的不断增加,不可靠性也会呈指数级增长,若10个服务串联在一起,就只能承诺99.9%,也就是3个9的在线时间占比了。

2.并行的可相互替代的服务实例

为了提高可靠性,一个服务经常会提供多个相对独立的、可相互替代的实例给用户使用,理想情况下,任意一个实例下线不会影响总体的服务质量,这是一种冗余设计。

在这种假设的基础上,只有当所有的实例都下线,这个服务作为一个整体才会算下线。假设每个实例的稳定性是99%(才两个9),有两个实例,那么这个服务的整体预期在线时间占比应该是

1-[1-99%*(1-99%)]=99.99%

立刻多了两个9,可靠性的提升立竿见影。多出来的这一个实例,称为冗余实例。

实际的应用中,这种冗余设计并不能达到上面假设的完美状态,但仍然可以满足应用它的初衷。

3.1.3 服务冗余的示例

为了提高服务的稳定性,为服务增加冗余服务实例是在不改变服务根本设计的前提下的一种常见方式。根据服务是否存在状态,可以将服务分为无状态服务和有状态服务。所谓状态,是指一个服务自身会记录跟外界交互的数据。例如,内容分发网络(CDN)是无状态服务,每次用户请求一个文件,它都不会根据用户的请求修改自身的某些内容,并且它总返回相同的结果。数据库则是有状态服务的最明显的例子。

根据一个服务的状态有无,它的冗余方式也有区别,下面举例说明两种类型服务的主流冗余方式。

1.无状态的网站服务

无状态的网站服务是最接近上面完美假设的例子,由于服务本身无状态(业务不需要或者状态被下游其他服务Z管理),网站服务实例之间可以被任意替代。

与完美的假设唯一不同的是网站的服务质量,并不是在所有的实例下线之后才会被外界察觉。由于网站会被多个用户访问,也许需要超过一个实例才能应付用户的访问,实例过少会出现用户打开页面或者处理业务延迟的情况。所以,只有超过必要数目的实例才能被称为冗余实例。

2.基于一致性哈希(Consistent Hash)的数据库服务Coachbase

Coachbase使用多个(设为N)节点(Node)去保存用户的数据,但是与前面完美的假设情况不同的是,每个节点只负责总数据量的一个子集,而每个子集之间相互重叠以达到冗余的目的。在某个节点负责的这个子集里,节点负责主动管理其中一部分的数据,而其他部分的数据它只负责被动地存储。对于任意数据,它会被一个主节点主动地管理(读、写、复制到冗余节点),而被多个(设为K,K<N)节点存储。主节点失效之后系统会把其中一个冗余节点提升为主节点。

也许读者已经看出来了,对于任意数据,冗余只限于它存在的那部分节点,并且主节点和多个节点之间的关系需要通过外力来调整。

3.1.4 提高稳定性的最佳实践

在工程师维护各个生产服务的过程中,逐渐总结出了一些比较通行的做法和建议,用于提高服务的稳定性,提升维护工作的效率,如如何设置监控和冗余。新上线的服务不需要从零开始考虑提高稳定性的设计,套用现有的做法即可。

1.监控关键组件

监控关键组件是发现线上问题最有效的方式之一,比如监控用户访问的API入口的错误信息和监控业务队列的长度。

一般而言,对组件的监控包括以下两方面。

● 对其性能表现的监控,一般是监控CPU、I/O和内存占用等指标。

● 对其业务处理状态的监控,一般以日志分析的方式做监控。

可以想象,就第一项而言,这是非常成熟的监控需求,而且由于大规模使用虚拟机,云服务可以提供现成的非侵入式的硬件指标监控。第二项通过约定格式和传输方式,应用产生的日志也可以被云的基础设施收集并展示。

以Azure为例,Azure Monitoring提供了包括各种指标和应用日志的统一监控系统,集合了收集、展示、分析、告警和输出的数据整个生命周期的服务,如图3-2所示。

图3-2 Azure的自动监控服务

2.对各部分稳定性设定清晰的需求

在系统的设计阶段,对各个子部件设定一个合理的稳定性需求,有助于对不同部件进行针对性的异常预案和冗余设计。

比如,在系统中需要用到硬盘来存储数据,那么也许在采购阶段就应该明确自己对硬盘稳定性的要求,并且根据采购的结果在系统设计阶段考虑所采用的硬盘的故障率(显然完全不会坏的硬件是不存在的)。假设采购的硬盘在其设计寿命内的无故障率是99%,而下游应用对硬盘的无故障率的要求是99.99%,那么把两个硬盘组成RAID 1阵列(任意数据在每块硬盘都有一份副本)之后,因为两块硬盘同时损坏而完全丢失数据的概率只有0.01%(即99.99%的无故障率),如果是三块硬盘,完全丢失数据的概率则降至0.0001%。

云服务对于自己的每一项组件,都会提供清晰的稳定性承诺(SLA),这极大地为系统设计提供了便利。云服务甚至允许根据不同的SLA需求支付不同的价格。

图3-3是Azure API管理对SLA的描述,主要内容是对于基本层级(Basic)、标准层级(Standard)、高级层级(Premium)和开发人员层级(Developer)的SLA的约定。

图3-3 Azure API管理对SLA的描述

3.尽可能自动化运维操作

人类执行操作时,即使有足够细致的文档说明,出错率也远高于完全自动化的系统。自动化的系统如果出了任意错误,经过调整后,下次它会忠实地执行新的方案,不会和人类一样,由于精力、情绪甚至人员变更等因素经常犯错。

云服务对资源的操作和访问都通过互联网提供给最终用户,决定了它必然存在可编程应用接口(API)等便于自动化运维的基础设施,天然支持自动化运维。

以Azure为例,Azure对于每种资源都提供了对应的Rest API来操作该资源,图3-4所示是Azure存储操作Blob(任意无结构数据)的API清单。

图3-4 Azure存储操作Blob的API清单

4.设计实时数据的备份

实时数据的备份又称为热备份,它所备份的是用户数据最新(或者接近最新)的状态,以便于在主存储设备出现故障时,尽快恢复状态。

用户数据的状态存储的是绝大多数系统的核心,正如在3.1.2节中并行的可相互替代的服务实例中提过的服务结构,如果可以实时地为数据提供存储冗余,那么存储将不会出现单点故障。在云服务之前,已经拥有了如下方案。

● 基于硬件的实时数据备份,如硬盘的各种RAID阵列(除了RAID 0)。

● 基于文件系统的实时数据备份,如软件实现的RAID、rsync,两者都有不同程序的延迟。

● 基于数据库的实时数据备份,比如PostgreSQL基于写入日志的多节点同步和3.1.3节中提及的Coachbase的备份。

在多数情况下,云服务提供的备份方式在本地环境也能做到,但云服务极大地简化了设置过程。甚至对于最基础的硬件,云服务(如AWS)也默认使用了备份措施,如硬盘的RAID阵列。

更近一步,云服务还会根据自己的特殊性提供独特的备份措施,比如由于云服务虚拟机(VPS)的硬盘模块大多是通过网络层跟VPS主体进行连接(AWS的EBS Volume,Azure的Managed Disk)的,所以云服务可以在网络层上对磁盘I/O进行热备份。

5.设计基于时间点的备份

基于时间点的备份(快照,Snapshot)虽然无法把系统恢复到最新的状态,会丢失从备份的时间点之后的所有数据。但是这类备份为各类误操作、程序错误和非法操作提供了一个撤销的机会。由于此种备份更多是逻辑设计的问题,跟本章主旨关系不大,在此不再展开。

云服务天然支持基于文件系统和基于数据库的快照,并且为基于快照的低使用频率提供了更加廉价的存储方式(见3.2节),更具性价比。

6.跨地理位置(多数据中心)提供服务冗余

把服务部署到多个数据中心,对于一般用户而言,无论是硬件、行政开销还是运维人员,都比单一数据中心的模式的成本大很多。而由于应用场景的特殊性,尤其是基于公共网络的传输效率,一些数据库的备份功能无法提供成熟的跨数据中心的同步服务。

而云服务由于规模效应的存在,用户在同一数据中心运行两台虚拟机,与在不同数据中心各运行一台虚拟机的开销是一样的。又由于大量数据中心之间通信的实践和数据中心之间的专用通信网络,云服务提供商天然对跨数据中心的备份有良好的支持,无论是文件系统级别的备份,还是程序级别的备份。Redis的跨数据中心备份就是很好的例子,Redis的官方团队提供了名为无冲突冗余数据集群(Conflict-Free Replicated Databases,CRDB)的解决方案,而Azure也提供了基于自己的流量管理器(Traffic Manager)的实现。