大型网站架构模式(四)

万无一失:网站的高可用架构


目录

万无一失:网站的高可用架构

一、网站可用性的度量与考核

1.1、网站可用性度量

1.2、网站可用性考核

二、高可用的网站架构

三、高可用的应用

3.1、通过负载均衡进行无状态服务的失效转移

3.2、应用服务器集群的Session管理

四、高可用的服务

五、高可用的数据

5.1、CAP原理

5.2、数据备份

5.3、失效转移

六、高可用网站的软件质量保证

6.1、网站发布

6.2、自动化测试

6.3、预发布验证

6.4、代码控制

6.5、自动化发布

6.6、灰度发布

七、网站运行监控

7.1、监控数据采集

7.2、监控管理

八、小结


2011年4月12日,亚马逊云计算服务EC2(Elastic Computer Cloud)发生故障,其ESB(Elastic Block Storage)服务不可用,故障持续了数天,最终还是有部分数据未能恢复。这一故障导致美国许多实用亚马逊云服务的知名网站(如:Foursquare、Quora)收到影响,并引发了人们对使用云计算安全性、可靠性的大规模讨论。

2010年1月12日,百度被黑客攻击,其DNS域名被劫持,导致百度全站长达数小时不可访问。该事件一时成为新闻焦点,各种媒体争相报道。

至此,网站的可用性(Availability)描述网站可有效访问的特性(不同于另一个网站运营指标:Usability,通常也被译作可用性,但是后者强调的是网站的有用性,即对最终用户的使用价值),相比于网站的其他非功能特性,网站的可用性更牵动人们的神经,大型网站的不可用事故直接影响公司形象和利益,许多互联网公司都将网站可用性列入工程师的绩效考核,与奖金升迁等利益挂钩。

一、网站可用性的度量与考核

网站的页面能完整呈现在最终用户面前,需要经过很多个环节,任何一个环节出了问题,都可能导致网站页面不可访问。DNS会被劫持、CDN服务可能会挂掉、网站服务器可能会宕机、网络交换机可能会失效、硬盘会损坏、网卡会松掉、甚至机房会停电、空调会失灵、程序会有Bug、黑客会攻击、促销会引来大量访问、第三方合作伙伴的服务会不可用……要保证一个网站永远完全可用几乎是意见不可能完成的使命。

1.1、网站可用性度量

网站不可用也被称作网站故障,业界通常用多少个9来衡量网站的可用性,如QQ的可用性是4个9,即QQ服务99.99%可用,这意味着QQ服务要保证其在所有运行时间中,只有0.01%的时间不可用,也就是一年中大约最多53分钟不可用。

网站不可用时间(故障时间)=故障修复时间点-故障发现(报告)时间点

网站年度可用性指标=(1-网站不可用时间/年度总时间)×100%

对于大多数网站而言,2个9是基本可用,网站年度不可用时间小于88小时;3个9是较高可用,网站年度不可用时间小于9小时;4个9是具有自动回复能力的高可用,网站年度不可用时间小于53分钟;5个9是极高可用性,网站年度不可用时间小于5分钟。

由于可用性影响因素很多,对于网站整体而言,达到4个9,乃至5个9的可用性,除了过硬的技术、大量的设备资金投入和工程的责任心,还要有个好运气。

常使用Twitter的用户或多或少遇到过那个著名服务器不可用的鲸鱼页面,事实上,Twitter的网站可用性不足2个9。

1.2、网站可用性考核

可用性指标是网站架构设计的重要指标,对外是服务承诺,对内是考核指标。从管理层面,可用性指标是网站或者产品的整体考核指标,具体到每个工程师的考核,更多的是使用故障分。

所谓故障分是只对网站故障进行分类和加权计算故障责任的办法。下表为某网站故障分类权重表。

故障分的计算公式为:

故障分=故障时间(分钟)× 故障权重

在年初或者考核季度的开始,会根据网站产品的可用性指标计算总的故障分,然后根据团队和个人的职责角色分摊故障分,这个可用性质保和故障分是管理预期。在实际发生故障的时候,根据故障分类和责任划分将故障产生的故障分配给责任者承担。等年末或者考核季度末的时候,个人及团队实际承担的故障分如果超过了年初分摊的故障分,绩效考核就会受到影响。

一个简化的故障处理流程,如下图所示。

有时候一个故障责任可能又多个部门或团队来承担,故障分也会相应按责任分摊到不同的团队和个人。

不同于其他架构指标,网站可用性更加看得见摸得着。跟技术、运营、相关各方的绩效考核息息相关,因此在架构设计与评审会议上,关于系统可用性的讨论与争执总是最花费时间和精力的部分。

当然,不同的公司有不同的企业文化和市场策略,这些因素也会影响到系统可用性的架构决策,冲上创新和风险的企业会对可用性要求稍低一些;业务快速增长的网站忙于应对指数级增长的用户,也会降低可用性的标准;服务于收费用户的网站则会比服务于免费用户的网站对于可用性更加敏感,服务不可用或关键用户数据丢失可能会导致收费用户的投诉甚至引来官司。

二、高可用的网站架构

通常企业级应用系统为提高系统可用性,会采用较昂贵的软硬件设备,如IBM的小型机乃至中型机大型机及专有操作系统、Oracle数据库、EMC存储设备等。互联网更多地采用PC级服务器、开源的数据库和操作系统,浙西廉价的设备在节约成本的同时也降低了可用性,特别是服务器硬件设备,低价的商业级服务器一年宕机一次是一个大概率事件,而那些高强度频繁读写的普通硬盘,损坏的概率则要更高一些。

既然硬件故障是常态,网站的高可用架构设计的主要目的就是保证服务器硬件故障时服务依然可用,数据依然保存并能够被访问。

实现上述高可用架构的主要手段是数据和服务的冗余备份及失效转移,一旦某些服务器宕机,就将服务器切换到其他可用的服务器上,如果磁盘损坏,则从备份的磁盘读取数据。

一个典型的网站设计通常遵循如下图所示的基本分层架构。

 

典型的分型模型是三层,即应用层、服务层、数据层;各层之间具有相对独立性,应用层主要负责具体业务逻辑处理;服务层负责提供可复用的服务;数据层负责数据的存储与访问。中小型网站在具体部署时,通常将应用层和服务层部署在一起,而数据层则另外部署,如下图所示(事实上,这也是网站架构演化)。

在复杂的大型网站架构中,划分的粒度会更小、更详细,结构更加复杂,服务器规模更加庞大,但通常还是能够吧这些服务器划分到这三层中。如下图所示。

不同的业务产品会部署在不同的服务器集群上,如某网站的文库、贴吧、百科等属于不同的产品,部署在各自独立的服务器集群上,互不相干。这些产品又会依赖一些宫廷的复用业务,如登录注册服务、Session管理服务、账户管理服务等,这些可复用的业务也各自部署在独立的服务器集群上。至于数据层,数据库服务、文件服务、缓存服务、搜索服务等数据存储与访问服务都部署在各自独立的服务器集群上。

    大型网站的分层架构及物理服务器的分布式部署使得位于不同层次的服务器具有不同的可用性特点。关闭服务或者服务器宕机时
产生的影响也不相同,高可用的解决方案也差异甚大。

位于应用层的服务器通常为了应对高并发的访问请求,会通过负载均衡设备将一组服务器组成一个集群共同对外提供服务,当负载均衡设备通过心跳检测等手段监控到某台服务器不可用时,就将其从集群列表中剔除,并将请求分发到集群宏其他可用的服务器上,使整个集群保持可用,从而实现高可用。

位于服务层的服务器情况和应用层服务器类似,也是通过集群方式实现高可用,只是这些服务器被应用层通过分布式服务调用框架访问,分布式服务调用框架会在应用层客户端程序中实现软件负载均衡,并通过服务注册中心对提供服务的服务器进行心跳检测,发现有服务不可用,立即通知客户端程序修改服务访问列表,剔除不可用的服务器。

位于数据层的服务器情况比较特殊,数据服务器上存储着数据,为了保证服务器宕机时数据不丢失,数据访问服务不中断,需要在数据写入时进行数据同步复制,将数据写入多台服务器上,实现数据冗余备份。当数据服务器宕机时,应用程序将访问切换到有备份数据的服务器上。

网站升级的频率一般都非常高,大型网站一周发布一次,中小型网站一天发布几次,每次网站发布都需要关闭服务,重新部署系统,整个过程相当于服务器宕机。因此网站的可用性架构设计不但要考虑实际的硬件故障引起的宕机,还要考虑网站升级发布引起的宕机,而后者更加频繁,不能因为系统可以接受偶尔的停机故障就降低可用性设计的标准。

三、高可用的应用

应用层主要处理网站应用的业务逻辑,因此有时也称作业务逻辑层,应用的一个显著特点是应用的无状态性。

所谓无状态的应用是指应用服务器不保存业务的上下文信息,而仅根据每次请求提交的数据进行相应的圆舞曲逻辑处理,多个服务实例(服务器)之间完全对等,请求提交到任意服务器,处理结果完全都是一样的。

3.1、通过负载均衡进行无状态服务的失效转移

不保存状态的应用给高应用的架构设计带来了巨大便利,既然服务器不保存请求的状态,那么所有的服务器完全对等,当任意一台或多台服务器宕机,请求提交给集群中其他任意一台可用机器处理,这样对终端用户而言,请求总是能够成功的,整个系统依然可用。对于应用服务器集群,实现这种服务器可用状态实时监测、自动转移失败任务的机制是负载均衡。

负载均衡,顾名思义,主要使用在业务量和数据量较高的情况下,当单台服务器不足以承担所有的负载压力时,通过负载均衡手段,将流量和数据分摊到一个集群组成的多台服务器上,以提高整体的负载处理能力。目前,不管是开源免费的负载均衡软件还是昂贵的负载均衡硬件,都提供失效转移功能。在网站应用中,当集群中的服务是无状态对等时,负载均衡可以起到事实上高可用的作用,如下图所示。

当WEB服务器集群中的服务器都可用时,负载均衡服务器会把用户请求发送的访问请求分发到任意一台服务器上进行处理,而当服务器10.0.0.1宕机时,负载均衡服务器通过心跳检测机制发现该服务器失去响应,就会把它从服务器列表删除,而将请求发送到其他服务器上,这些服务器是完全一样的,请求在任何一台服务器中处理都不会影响最终的结果。

由于负载均衡在应用层实际上起到了系统高可用的作用,因此即使某个应用访问量非常少,只用一台服务器提供服务就绰绰有余,但如果需要保证该服务高可用,也必须至少部署两台服务器,使用负载均衡即使构建一个小型的集群。

3.2、应用服务器集群的Session管理

应用服务器的高可用架构设计主要基于服务无状态这一特性,但事实上,业务总是有状态的,在交易类的电子商务网站,需要有购物车记录用户的购买信息,用户每次购买请求都是向购物车中增加商品;在社交类的网站中,需要记录用户的房钱登录状态、最新房补的消息及好友黄台等,用户每次刷新页面都需要更新这些信息。

Web应用中奖这些请求修改使用的上下文对象称作会话(Session),单机情况下,Session可由部署在服务器上的Web容器(如JBoss)管理。在使用负载均衡的集群环境中,由于负载均衡服务器可能会将请求分发到集群任何一台服务器上,所以保证每次请求依然能够获得正确的Session比单机时要复杂很多。

集群环境下,Session管理主要有以下几种手段。

1、Session复制

Session复制是早期企业引用系统使用较多的一种服务器集群Session管理机制。应用服务器开启Web容器的Session复制功能,在集群中的几台服务器之间同步Session对象,使得每台服务器上都保存所有用户的Session信息,这样任何一台机器宕机都不会导致Session数据的丢失,而服务器使用Session时,也只需要在本机获取即可。如下图所示

这种方案虽然简单,从本机读取Session信息也很快速,但只能使用在集群规模比较小的情况下。当集群规模较大时,集群服务器间需要大量的通信进行Session赋值,占用服务器和网络的大量资源,系统不堪负担。由于所有用户的Session信息在每台服务器上都有备份,在大量用户访问的情况下,甚至会出现服务器内存不够Session使用的情况。

而大型网站的核心应用集群就是数千台服务器,同时在线用户可达千万,因此不适用这种方案。

2、Session绑定

Session绑定可以利用负载均衡的原地址Hash算法实现,负载均衡服务器总是将来源于同一IP的请求分发到同一台服务器上(也可以根据Cookie信息将同一个用户的请求总是分发到同一台服务器上,淡然这时负载均衡服务器必须工作在HTTP协议蹭上,关于负载均衡算法的更多信息请参考我们下一节的内容)。这样整个会话期间,用户所有的请求都在同一台服务器上处理,即Session绑定在某台特定服务器上,保证Session总能在这台服务器上获取。这种方法又被称作会话粘滞,如下图所示。

但是Session绑定的方案显然不符合我们对系统高可用的需求,因为一旦某台服务器宕机,那么该机器上的Session也就不复存在了,用户请求切换到其他机器后因为没有Session而无法完成业务处理。因此虽然大部分负载金恒服务器都提供原地址负载均衡算法,但很少有网站利用这个算法进行Session管理。

3、利用Cookie记录Session

早期的企业应用系统使用C/S(客户端/服务器)架构,一种管理Session的方式是将Session记录在客户端,每次请求服务器的时候,将Session放在请求中发给服务器,服务器处理完请求后再将修改过的Session响应给客户端。

网站没有客户端,但是可以利用浏览器支持的Cookie记录Session,如下图所示。

利用Cookie记录Session也有一些缺点,比如受Cookie大小限制,能记录的信息有限;每次请求响应都需要传输Cookie,影响性能;如果用户关闭Cookie,访问就会不正常。但是由于Cookie的简单易用,可用性高,支持应用服务器的线性伸缩,而大部分应用需要记录的Session信息又比较小。因此事实上,很多网站都或多或少地使用Cookie记录Session。

4、Session服务器

那么没有可用性高、伸缩性好、性能也不错,对信息大小又没有限制的服务器集群Session管理方案呢?

答案就是Session服务器。利用独立部署的Session服务器(集群)统一管理Session,应用服务器每次读写Session时,都访问Session服务器,如下图所示。

这种解决方案事实上是将应用服务器的状态分离,分为无状态的应用服务器和有状态的Session服务器,然后针对这两种服务器的不同特性分别设计其架构。

对于有状态的Session服务器,一种比较简单的放大是利用分布式缓存、数据库等,在这些产品的基础上进行包装,使其符合Session的存储和访问要求。如果业务场景对Session管理有比较高的要求,比如利用Session服务器集成单点登录(SSO)、用户服务等功能,则需要开发专门的Session服务管理平台。

四、高可用的服务

可复用的服务模块为业务产品提供基础公共服务,大型网站中这些服务通常都独立分布式部署,被具体应用远程调用。可复用的服务和应用一样,也是无状态的服务,因此可以使用类似负载均衡的失效转移策略实现高可用的服务。

除此之外,具体实践中,还有以下几点高可用的服务策略。

1、分级管理

运维上将服务器进行分级管理,核心应用和服务器优先使用更好的硬件,在运维响应速度上也格外迅速。显然,用户及时付款购物比能不能评价商品更重要,所以订单、支付服务比评价服务有更高优先级。

同时在服务器不是上也进行必要的隔离,避免故障的连锁反应。低优先级的服务通过启动不同的线程或者部署在不同的虚拟机上进行隔离,而高优先级的服务则需要部署在不同的物理机上,核心服务和数据甚至需要部署在不同地域的数据中心。

2、超时设置

由于服务端宕机、线程死锁等原因,可能导致应用程序对服务端调用失去响应,进而导致用户请求长时间得不到响应,同时还占用应用程序的资源,不利于及时将访问请求转移到正常的服务器上。

在应用程序中设置服务调用的超时时间,一旦超时,通信框架就抛出异常,应用程序根据服务调度策略,可选择继续重试或将请求转移到提供相同服务的其他服务器上。

3、异步调用

应用对服务的调用通过消息队列等异步方式完成,避免一个服务失败导致整个应用请求失败的情况。如果提交一个新用户注册请求,应用需要调用三个服务:将用户信息写入数据库,发送账户注册成功邮件,开通对应权限。如果采用同步服务调用,当邮件队列阻塞不能发送邮件时,会导致其他两个服务也无法执行,最终导致注册失败。

如果采用异步调用的方式,应用程序将用户注册信息发送给消息队列服务器后立即返回用户注册成功响应。而记录用户注册信息到数据库、发送用户注册成功邮件、调用用户服务开通权限这三个服务作为消息的消费者任务,分别从消息队列获取用户注册信息异步执行。即使邮件服务队列阻塞,邮件不能成功发送,也不会影响其他服务的执行,用户注册操作可顺利完成,只是晚一点收到注册成功的邮件而已。

当然不是所有的服务调用都可以异步调用,对于获取用户信息这类调用,采用异步方式会延长响应时间,得不偿失。对于那些必须确认服务调用成功才能继续下一步操作的应用也不合适使用异步调用。

4、服务降级

在网站访问高峰期,服务可能因为大量的并发调用而性能下降,严重时可能会导致服务宕机。为了保证核心应用和功能的正常运行,需要对服务进行降级。降级有两种手段:拒绝服务及关闭服务。

拒绝服务:拒绝低优先级应用的调用,减少服务调用并发数,确保核心应用正常的使用;或者随机拒绝部分请求调用,节约资源,让另一部分请求得以成功,避免要死大家一起死的惨剧。貌似Twitter比较喜欢使用随机拒绝请求的策略,经常有用户看到请求失败的故障页面,但是问下身边的人,其他人都正常使用,自己在刷新页面,也好了。

关闭功能:关闭部分不重要的服务,或者服务内部关闭部分不重要的功能,以节约系统开销,为重要的服务和功能让出资源。淘宝在每年的“双十一”促销中就使用这种方法,在系统最繁忙的时段关闭“评价”、“确认收货”等非核心服务,以保证核心交易服务的顺利完成。

5、幂等性设计

应用调用服务失败后,会将嗲用请求重新发送到其他服务器,但是这个失败可能是虚假的失败。比如服务已经处理成功,但因为网络故障应用没有收到响应,这时应用重新请求就导致服务重复调用,如果这个服务是一个转账操作,就会产生严重后果。

服务重复调用时无法避免的,应用层也不需要关系服务是否真的失败,只要没有收到调用成功的响应,就可以认为调用服务,并重试服务调用。因此必须在服务层保证服务重复调用和调用一次产生的结果相同,即服务具有幂等性。

有些服务天然具有幂等性,比如将用户性别设置为男性,不管设置多少次,结果都是一样。但是对于转账交易等操作,问题就会比较复杂,需要通过交易编号等信息进行服务调用的有效校验,只有有效的操作才能继续执行。

五、高可用的数据

对许多网站而言,数据是其最宝贵的物质资产,硬件可以购买,软件可以重写,但是多年运营积淀下来的各种数据(用户数据、交易数据、商品数据……),代表着历史已经成为过去们不能再重来,一旦失去,对网站的打击可以说是毁灭性的。因此可以说,保护网站的数据就是保护企业的命脉。

不同于高可用的应用和服务,由于数据存储服务器上保存的数据不同,当某台服务宕机的时候,数据访问请求不能任意切换到集群中的其他机器上。

保证数据存储高可用的手段主要是数据备份失效转移机制。数据备份是保证数据有多个副本,任意副本的失效都不会导致数据的永久丢失,从而实现数据完全的持久化。而失效转移机制则保证当一个数据副本不可访问时,快速切换访问数据的其他副本,保证系统可用。

关于缓存服务的高可用,在实践中争议很大,一种观点认为缓存已经成为网站数据服务的重要组成部分,事实上承担了业务中绝大多数的数据读取访问服务,缓存服务时效可能会导致数据库负载过高而宕机,进而影响整个网站的可用性,因此缓存服务需要实现和数据存储服务同样的高可用。

另一种观点认为,缓存服务不是数据存储服务,缓存服务器宕机引起缓存数据丢失导致服务器压力过高应该通过其他手段解决,而不是提高缓存服务本身的高可用。

对于缓存服务器集群中的单机宕机,如果缓存服务器集群规模较大,那么单机宕机引起的缓存数据丢失比例和数据库负载压力变化都比较小,对整个系统影响也较小。扩大缓存服务器集群规模的一个简单手段就是整个网站共享同一个分布式缓存集群,单独的应用和产品不需要部署自己的缓存服务器,只需要向共享缓存集群申请缓存资源即可。并且通过逻辑或物理分区的方式将每个应用的缓存部署在多态服务器上,任何一台服务器宕机引起的缓存失效都只影响应用缓存数据的一小部分,不会对应用性能和数据库负载造成太大影响。

5.1、CAP原理

在讨论高科用户数服务架构之前,必须先讨论一个话题是,为了保证数据的高可用,网站通常会牺牲另一个也很重要的指标:数据一致性。

高可用的数据有如下几个层面的含义。

数据持久性

保证数据可持久存储,在各种情况下都不会出现数据丢失的问题。为了实现数据的持久性,不但在写入数据时需要写入持久性存储,还需要将数据备份一个或到哦个副本,存放在不同的物理存储设备上,在某个存储故障或灾害发生时,数据不会丢失。

数据可访问性

保证数据可持久存储,在各种情况下都不会出现数据丢失的问题。为了实现数据的持久性,不但在写入数据时需要写入持久性存储,还需要将数据备份一个或多个备份,存放在不同的物理存储设备上,在某个存储故障或灾害发生时,数据不会丢失。

数据可访问性

在多份数据副本分别存放在不同存储设备的情况下,如果一个数据存储设备损坏,就需要将数据访问切换到另一个数据存储设备上,如果这个过程不能很快完成(终端用户几乎没有感知),或者完成过程中需要停止终端用户访问数据,那么这段时间数据是不可访问的。

数据一致性

在数据有多份副本的情况下,如果网络、服务器或者软件出现故障,会导致部分副本写入成功,部分副本写入失败。这就会造成各个副本之间的数据不一致,数据内容冲突。实践中,导致数据不一致的情形有很多种,表现形式也多种多样,比如数据更新返回操作失败,事实上数据在存储服务器已经跟新成功。

CAP原理认为,一个提供数据服务的存储系统无法同时满足数据一致性(Consistency)、数据可用性(Availability)、分区耐受性(Patition Tolerance,系统具有跨网络分区的伸缩性)这三个条件,如下图所示,

在大型网站应用中,数据规模总是快速扩张的,因此可伸缩性即分区耐受性必不可少,规模变大以后,机器数量也会变得庞大,这时网络和服务器故障会频繁出现,要想保证应用可用,就必须保证分布式处理系统的高可用性。所以在大型网站中,通常会选择强化分布式存储系统的可用性(A)和伸缩性(P),而在某种程度上放弃一致性(C)。一般来说,数据不一致通常出现在系统高并发写操作或者集群状态不稳(故障恢复、集群扩容……)的情况下,应用系统需要对分布式数据处理系统的数据不一致有所了解并进行某种意义上的补偿和纠错,以避免出现应用系统数据不正确。

2012年淘宝“双十一”活动期间,在互动第一分钟就涌入1000万独立用户访问,这种极端的高并发场景对数据处理系统造成了巨大压力,存储系统较弱的数据一致性导致出现部分商品超卖现象(交易成功的商品数超过了商品库存数)。

CAP原理对于可伸缩性的分布式系统设计须有重要意义,在系统设计开发过程中,不恰当地迎合各种需求,企图打造一个完美的产品,可能会使设计进入两难境地,难以为继。

具体来说,数据一致性又可分为如下几点。

数据强一致

各个副本的数据在无力存储中总是一致的;数据更新操作结果个操作响应总是一致的,即操作响应通知更新失败,那么数据一定没有被更新,而不是出于不确定状态。

数据用户一致

即数据在无力存储中的各个副本的数据硁硁是不一致的,但是终端用户访问时,通过纠错和校验机制,可以确定一个一致的且争取的数据返回给用户。

数据最终一致

这是数据一致性中较弱的一种,即物理存储的数据可能是不一致的,终端用户访问到的数据可能也是不一致的(同一用户连续访问,结果不同;或者不同用户同时访问,结果不同),单系统经过一段时间(通常是一个比较短的时间段)的自我修复和修正,数据最终会达到一致。

因为难以满足数据强一致性,网站通常会综合成本、技术、业务场景等条件。结合应用服务和其他的数据监控与纠错功能,使存储系统达到用户一致,保证最红用户访问数据的正确性。

5.2、数据备份

数据备份是一种古老而有效的数据保护手段,早起的数据备份手段主要是数据冷备,即定期将数据复制到某种存储介质(磁盘,光盘……)上并物理存档保管,如果系统存储损坏,那么久从冷备的存储设备中恢复数据。

冷备的有点是简单和廉价,成本和技术难度都比较低。缺点是不能保证数据最终一致,由于数据是定期复制,因此备份设备中的数据比系统冲的数据陈旧,如果系统数据丢失,那么从上个备份点开始后更新的数据就会永久丢失,不能从备份中恢复。同时也不能保证数据可用性,从冷备存储中恢复数据需要较长的时间,而这段时间无法访问数据,系统也不可用。

因此,数据冷备作为一种传统的数据保护手段,依然在网站日常运维中使用,同时在网站实时在线业务中,还需要进行数据热备,以提供更好的数据可用性。

数据热备可分为两种:异步热备方式和同步热备方式。

异步方式是指多份数据副本的写入操作异步完成,应用程序收到数据服务系统的写操作成功响应时,只写成功了一份,存储系统将会异步的写其他副本(这个过程有可能会失败)。如下图所示。

在异步写入方式下,存储服务器分为主存储服务器(Master)和从存储服务器(Slave),应用程序正常情况下只连接主存储服务器,数据写入时,由主存储服务器的写操作代理模块将数据写入本机存储系统后立即返回写操作成功响应,然后通过异步线程将写操作数据同步到从存储服务器。

同步方式是指多份数据副本的写入操作同步完成。,即应用程序收到数据服务系统的写成功响应时,多份数据都已经写操作成功。但是当应用程序收到数据写操作失败的响应时,可能又部分副本或者全部副本都已经写成功了(因为网络或者系统故障,无法返回操作成功的响应),如下图所示。

 

同步热备具体实现的时候,为了提高性能,在应用程序客户端并发想多个存储服务器同时写入数据,然后等待所有存储服务器都返回操作成功的响应后,再通知应用程序写操作成功。

这种情况下,存储服务器没有主从之分,完全对等,更便于管理和维护。存储服务客户端在写多份数据的时候,并发操作,这意味着多份数据的总写操作延迟是响应最慢的那台存储服务器响应延迟,而不是多台存储服务器响应延迟之和。其性能和异步热备方式差不多。

传统的企业级关系数据库系统几乎都提供了数据实时同步备份的机制。而一开始就为大型网站而设计的各种NoSQL数据库(如HBase)更是将数据备份机制作为产品最除妖的功能点之一。

关系数据库热备机制就是通常所说的Master-Slave同步机制。Master-Slave机制不但解决了数据备份问题,还干山了数据库系统的性能,实践中,通常使用读写分离的方法访问Slave和Master数据库,写操作只访问Master数据库,读操作只访问Slave数据库。

5.3、失效转移

若数据服务器集群中的任何一台服务器宕机,那么应用程序针对这台服务器的所有读写操作都需要重新路由到其他服务器,保证数据访问不会失败,这个过程叫做失效转移。

失效转移操作由三部分组成:失效确认、访问转移、数据恢复。

1、失效确认

判断服务器宕机是系统进行失效转移的第一步,系统确认一台服务器是否宕机的手段有两种:心跳检测和应用程序访问失败报告,如图所示。

对于应用程序的访问失败报告,控制中心还需要再一次发送心跳检测进行确认,以免错误判断服务器宕机,因为一旦进行数据访问的失效转移,就以为这数据存储多份副本不一致,需要进行后续一系列复杂的操作。

2、访问转移

确认某台数据存储服务器宕机后,就要将数据读写访问重新路由到其他服务器上,对于完全对等存储的服务器(几台存储服务器存储的数据完全一样,我们称几台服务器为对等服务器,比如主从结构的存储服务器,其存储的数据完全一样),当其中一台宕机后,应用程序根据配置直接切换到对等服务器上。如果存储是不对等的,那么久需要从新计算路由,选择存储服务器。

3、数据恢复

因为某台服务器宕机,所以数据存储的副本数据会减少,必须将副本的数目恢复到系统设定的值,否则,再有服务器宕机时,就可能出现无法访问转移(所有副本的服务器都宕机了),数据永久丢失的情况。因此系统需要从健康的服务器赋值数据,将数据副本数目恢复到设定值。

六、高可用网站的软件质量保证

在网站运维实践中,除了网络、服务器等硬件故障导致的系统可用性风险外,还有来自软件系统本身的风险。

关于传统的软件测试和软件质量保证管理无需赘言,本节重点讨论网站为了保证线 上系统的可用性而采取的一些与传统软件开发不同的质量保证手段。

6.1、网站发布

网站需要保证7x24高可用运行,同时网站又需要不断地发布新功能吸引用户以保证 在激烈的市场竞争中获得成功。许多大型网站每周都需要发布-到两次,而中小型网站 则更加频繁,一些处于快速发展期的网站甚至每天发布十几次。

不管发布的新功能是修改了一个按钮的布局还是增加了一个核心业务,都需要在服 务器上关闭原有的应用,然后重新部署启动新的应用,整个过程还要求不影响用户的使 用。这相当于要求给飞行中的飞机换个引擎,既不能让飞机有剧烈晃动(影响用户体验), 也不能让飞机降落(系统停机维护),更不能让飞机坠毁(系统故障网站完全不可用)。

网站的发布过程事实上和服务器宕机效果相当,其对系统可用性的影响也和服务器 宕机相似。所以设计一个网站的高可用架构时,需要考虑的服务器宕机概率不是物理上 的每年- -两次,而是事实上的每周一两次。也许你认为这个应用不重要,重启也非常快, 用户可以忍受每年一到两次的宕机故障, 因而不需要复杂的高可用设计。事实上,由于 应用的不断发布,用户需要面对的是每周一到两次的宕机故障。

但是网站发布毕竟是- -次提前预知的服务器宕机,所以过程可以更柔和,对用户影 响更小。通常使用发布脚本来完成发布,其流程如图所示。

发布过程中,每次关闭的服务器都是集群中的一小部分,并在发布完成后立即可以 访问,因此整个发布过程不影响用户使用。

6.2、自动化测试

代码在发布到线上服务器之前需要进行严格的测试。即使每次发布的新功能都是在 原有系统功能上的小幅增加,但为了保证系统没有引入未预料的Bug,网站测试还是需要 对整个网站功能进行全面的回归测试。此外还需要测试各种浏览器的兼容性。在发布频 繁的网站应用中,如果使用人工测试,成本、时间及测试覆盖率都难以接受。

目前大部分网站都采用Web自动化测试技术,使用自动测试工具或脚本完成测试。 比较流行的Web自动化测试工具是ThoughtWorks开发的Selenium。 Selenium运行在浏览 器中,模拟用户操作进行测试,因此Selenium可以同时完成Web功能测试和浏览器兼容 测试。

大型网站通常也会开发自己的自动化测试工具,可以一键完成系统部署,测试数据 生成、测试执行、测试报告生成等全部测试过程。许多网站测试I程师的编码能力毫不 逊于软件工程师。

6.3、预发布验证

即使是经过严格的测试,软件部署到线上服务器之后还是经常会出现各种问题,甚 至根本无法启动服务器。主要原因是测试环境和线上环境并不相同,特别是应用需要依 赖的其他服务,如数据库,缓存、公用业务服务等,以及- -些第三方服务,如电信短信 网关、银行网银接口等。

也许是数据库表结构不- -致; 也许是接口变化导致的通信失败;也许是配置错误导致 连接失败;也许是依赖的服务线上环境还没有准备好,这些问题都有可能导致应用故障。

因此在网站发布时,并不是把测试通过的代码包直接发布到线上服务器,而是先发 布到预发布机器上,开发工程师和测试工程师在预发布服务器上进行预发布验证,执行 一些典型的业务流程,确认系统没有问题后才正式发布。

预发布服务器是一种特殊用途的服务器,它和线上的正式服务器唯- -的不同就是没 有配置在负载均衡服务器上,外部用户无法访问,如图所示。

预发布服务器和线上正式服务器(应用服务器1, 2, 3 )都部署在相同的物理环境(同一个数据中心甚至同一个机架上,如果使用虚拟机,甚至可能在同一个物理服务器上) 中,使用相同的线上配置,依赖相同的外部服务。网站工程师通过在自己的开发用计算 机上配置hosts文件绑定域名IP关系直接使用IP地址访问预发布服务器。如果在预发布 服务器上执行的测试验证是正确的,基本可以确保在线上正式服务器部署时也没有问题。

不过,也有可能会因为预发布验证而引入问题。因为预发布服务器连接的是真实的 生产环境,所有的预发布验证操作都是真实有效的数据,这些操作也许会引起不可预期 的问题。比如创建一个店铺,上架一个商品,就有可能有真的用户过来购买,如果不能 发货,会导致用户投诉。

一个真实的案例是某网站需要验证海外第三方支付功能,每件商品的售价本来是数千美金,工程师不可能花数千美金去验证自己开发的功能,于是将金额改成一美元,验 证成功后,幸福地发布上线了,第二天上班后,发现大量商品以一美元的价格成交。

6.4、代码控制

对于大型网站,核心应用系统和公用业务模块涉及许多团队和工程师,需要对相同 的代码库进行共同开发和维护。而这些团队对同-个应用的开发维护(开发周期和发布. 时间点各不相同),如果代码控制环节出了问题,可能将有问题的代码发布上线,将问题 带入生产环境,导致系统故障。

网站代码控制的核心问题是如何进行代码管理,既能保证代码发布版本的稳定正确, 同时又能保证不同团队的开发互不影响。

目前大部分网站使用的源代码版本控制工具是SVN, SVN代码控制和版本发布方式 一般有以下两种。

1、主干开发、分支发布

代码修改都在主干(trunk).上进行,需要发布的时候,从主干.上拉-一个分支( branch ) 发布,该分支即成为一个发布版本,如果该版本发现Bug,继续在该分支上修改发布,并将修改合并( merge)回主干,直到下次主干发布。

2、分支开发,主干发布

任何修改都不得在主干上直接进行,需要开发一个新功能或者修复-一个Bug时,从 主干拉一个分支进行开发,开发完成且测试通过后,合并回主干,然后从主干进行发布, 主干.上的代码永远是最新发布的版本。

这两种方式各有优缺点。主干开发、分支发布方式,主干代码反应目前整个应用的 状态,一目了然,便于管理和控制,也利于持续集成。分支开发,主干发布方式,各个 分支独立进行,互不干扰,可以使不同发布周期的开发在同一应用中进行。

目前网站应用开发中主要使用的是分支开发、主干发布的方式,如图所示。

可以想象,如果使用主干开发、分支发布,那么在同-个应用上,对于不同开发周 期,不同发布时间的项目,有可能A项目发布的时候,B项目只开发了一半,这时候的 主干代码是半成品,根本不能发布。而使用分支开发、主干发布的方式,只需要将A项 目的分支合并回主干即可发布,不受B项目发布时间的影响。

目前在开源技术社区,Git 作为版本控制工具,正逐步取代SVN的地位。Git 对分布 式开发,分支开发等有更好的支持,也更容易在各个开发分支上及时反映主干的最新更 新,避免SVN在最后提交分支代码时发现和主干代码差别太大难以merge成功。但是Git 的学习成本较高,如何和网站开发流程相结合还缺乏最佳实践和使用规范。不过相信Git 成为网站的标准版本控制工具是迟早的事。

6.5、自动化发布

网站的版本发布频繁,整个发布过程需要许多团队通力合作,发布前,多个代码分 支合并回主干可能会发生冲突( conflict),预发布验证也会带来风险,每次发布又相当于 一次宕机事故。因此网站发布过程荆棘丛生,一不小心就会踩到雷。

对于有固定发布日期的网站(很多网站选择周四作为发布日,这样一周前面有三天 时间可以准备发布,后面还有一天时间可以挽回错误。如果选择周五发布,发现问题就必须要周末加班了), 一到发布日,整个技术部门甚至运营部门门就如临大敌,电话声此起彼伏,工程师步履匆匆,连空气中的温度都仿佛升高了几度。即便如此,发布过程还是常常出错,发布日工程师加班到凌晨是常有的事。而且容易忙中出错,因发布引发的 故障也居高不下。

据说国外某知名互联网公司的CTO就因为没有有效手段控制发布故障、减少发布日 的加班而引咎辞职。其继任者提出了一个火车发布模型:将每个应用的发布过程看作一 次火车旅程,火车定点运行,期间有若干站点,每一站都进行例行检查,不通过的项目 下车,剩下的项目继续坐着火车旅行,直到火车到达终点(应用发布成功)。但实际中, 有可能所有项目都下车了,开着空车前进是没有意义的,火车不得不回到起点,等待解 决了问题再重来-一次。还有可能是车上有达官贵人(重点项目,CEO跟投资人拍胸脯的 项目),他不上车,谁也别想走,他出了错,大家都跟着回去重来。简化的火车发布模型 如图所示。

由于火车发布模型是基于规则驱动的流程,所以这个流程可以自动化。采用火车发 布模型的网站会开发-一个自动化发布的工具实现发布过程的自动化。根据响应驱动流程, 自动构造代码分支,进行代码合并,执行发布脚本等。正常流程下,可以做到发布过程无人值守,无需SCM (网站配置管理员)参与,每个项目相关人员基于流程执行相应的 操作,即可完成应用自动发布。人的干预越少,自动化程度越高,引入故障的可能性就 越小,火车准点到达,大家按时下班的可能性就越大。

6.6、灰度发布

应用发布成功后,仍然可能发现因为软件问题而引入的故障,这时候就需要做发布 回滚,即卸载刚刚发布的软件,将上一个版本的软件包重新发布,使系统复原,消除故障。

大型网站的主要业务服务器集群规模非常庞大,比如某大型应用集群服务器数量超 过一万台。一旦发现故障,即使想要发布回滚也需要很长时间才能完成,只能眼睁睁看 着故障时间不断增加却干着急。为了应付这种局面,大型网站会使用灰度发布模式,将 集群服务器分成若干部分,每天只发布一- 部分服务器,观察运行稳定没有故障,第二天 继续发布一部分服务器,持续几天才把整个集群全部发布完毕,期间如果发现问题,只 需要回滚已发布的一部分服务器即可。如图所示。

灰度发布也常用于用户测试,即在部分服务器上发布新版本,其余服务器保持老版 本(或者发布另一个版本),然后监控用户操作行为,收集用户体验报告,比较用户对两个版本的满意度,以确定最终的发布版本。这种手段也被称作AB测试。

七、网站运行监控

“不允许没有监控的系统上线”,这是许多网站架构师在做项目上线评审时常说的- - 句话。网站运行监控对于网站运维和架构设计优化至关重要,运维没有监控的网站,犹如驾驶没有仪表的飞机。盲人骑瞎马,夜半临深渊而不知,生死尚且未卜,提高可用性、减少故障率就更无从做起了。

7.1、监控数据采集

广义上的网站监控涵盖所有非直接业务行为的数据采集与管理,包括供数据分析师 和产品设计师使用的网站用户行为日志、业务运行数据,以及供运维工程师和开发工程 师使用的系统性能数据等。

1、用户行为日志收集

用户行为日志指用户在浏览器上所做的所有操作及其所在的操作环境,包括用户操 作系统与浏览器版本信息,IP地址、页面访问路径、页面停留时间等,这些数据对统计 网站PV/UV指标、分析用户行为、优化网站设计、个性化营销与推荐等非常重要。

具体用户行为日志收集手段有两种。

服务器端日志收集。这个方案比较简单,Apache 等几乎所有Web服务器都具备日志 记录功能,可以记录大部分用户行为日志,开启Web服务器的日志记录功能即可。其缺 点是可能会出现信息失真,如IP地址是代理服务器地址而不是用户真实IP;无法识别访 问路径等。

客户端浏览器日志收集。利用页面嵌入专门的JavaScript 脚本可以收集用户真实的操 作行为,因此比服务器日志收集更加精准。其缺点是比较麻烦,需要在页面嵌入特定的 JavaScript脚本来完成。

此外,大型网站的用户日志数据量惊人,数据存储与计算压力很大,目前许多网站 逐步开发基于实时计算框架Storm的日志统计与分析工具。

2、服务器性能监控

收集服务器性能指标,如系统Load、内存占用、磁盘I0、网络10等对尽早做出故 障预警,及时判断应用状况,防患于未然,将故障扼杀在萌芽时期非常重要。此外根据 性能监控数据,运维工程师可以合理安排服务器集群规模,架构师及时改善系统性能及 调整系统伸缩性策略。

目前网站使用比较广泛的开源性能监控工具是Ganglia,它支持大规模服务器集群, 并支持以图形的方式在浏览器展示实时性能曲线。

3、运行数据报告

除了服务器系统性能监控,网站还需要监控- -些与具体业务场景相关的技术和业务 指标,比如缓冲命中率、平均响应延迟时间、每分钟发送邮件数目、待处理的任务总数 等。

对于服务器性能监控,网站运维人员可以在初始化系统时统-部署, 应用程序开发 完全不关心服务器性能监控。而运行数据需要在具体程序中采集并报告,汇总后统一显 示,应用程序需要在代码中处理运行数据采集的逻辑。

7.2、监控管理

监控数据采集后,除了用作系统性能评估、集群规模伸缩性预测等,还可以根据实 时监控数据进行风险预警,并对服务器进行失效转移,自动负载调整,最大化利用集群 所有机器的资源。

系统报警

在服务器运行正常的情况下,其各项监控指标基本稳定在-一个特定水平,如果这些 指标超过某个阈值,就意味着系统可能将要出现故障,这时就需要对相关人员报警,及 时采取措施,在故障还未真正发生时就将其扼杀在萌芽状态。

监控管理系统可以配置报警阈值和值守人员的联系方式,报警方式除了邮件,即时 通信工具,还可以配置手机短信,语音报警,系统发生报警时,工程师即使在千里之外、 夜里睡觉也能被及时通知,迅速响应。

失效转移

除了应用程序访问失败时进行失效转移,监控系统还可以在发现故障的情况下主动 通知应用,进行失效转移。

自动优雅降级

优雅降级是指网站为了应付突然爆发的访问高峰,主动关闭部分功能,释放部分系统资源,保证网站核心功能正常访问的-一个手段。淘宝每年一次的“双十一”促销活动 主动关闭“评价”、“确认收货”等非核心功能,以保证交易功能的正常进行,就可以看作 是一种优雅降级。

网站在监控管理基础之上实现自动优雅降级,是网站柔性架构的理想状态:监控系 统实时监控所有服务器的运行状况,根据监控参数判断应用访问负载情况,如果发现部 分应用负载过高,而部分应用负载过低,就会适当卸载低负载应用部分服务器,重新安 装启动部分高负载应用,使应用负载总体均衡,如果所有应用负载都很高,而且负载压 力还在继续增加,就会自动关闭部分非重要功能,保证核心功能正常运行。

八、小结

对公司而言,可用性关系网站的生死存亡。对个人而言,可用性关系到自己的绩效 升迁。工程师对架构做了许多优化、对代码做了很多重构,对性能、扩展性、伸缩性做 了很多改善,但别人未必能直观地感受到,也许你的直接领导都不知道你做的这些意义 何在。但如果你负责的产品出了重大故障,CEO都会知道你的名字。事物总是先求生存, 然后求发展。保证网站可用,万无一失,任重而道远。

 

如果小伙伴们想了解更多的内容,可以加群技术交流哦:1021060510

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值