面向业务的立体化高可用架构设计

面向业务的立体化高可用架构设计程序员

摘要:为了实现阿里九游游戏接入系统的业务高可用,技术人员跳出传统的面向系统的高可用的思路,转而从业务的角度来总体考虑高可用,最终实现了一套立体化的高可用架构,本文逐一展现这套立体化高可用架构的一些具体实践。redis

 

一般状况下咱们在谈论高可用架构设计的时候,主要关注的是系统结构的高可用,例如主备架构、集群架构、多中心架构。咱们作架构设计的时候,也主要是从系统结构自己出发,例如咱们把单机改成双机、双机改成集群、单机房改成异地多机房等等。算法

这种以系统结构为目标的高可用架构设计,更多的是从技术角度出发,但其实咱们都知道,不管技术多先进,架构多强大,都不可能保证100%不出问题的。蓝翔的挖掘机一铲子下去,支付宝就要故障2小时;程序员的误操做,携程12小时不能提供业务;某个黑客1000台肉鸡攻过来,网站可能就拒绝服务了......数据库

所以,真正作到高可用,不能单纯从系统结构的角度出发来考虑问题,不能局限于某个系统的高可用,而应该从业务的角度出发,全方位的来考虑高可用的架构设计。前者我称之为“面向系统的高可用架构”,后者我称之为“面向业务的高可用架构”。编程

阿里九游游戏接入系统(如下简称“游戏接入系统”)负责全部九游平台游戏的接入(包括用户的登陆、注册、支付等业务,也包括游戏开发商(如下简称“CP”)用户验证、支付等业务),对可用性的要求很是高,一旦故障,大量用户就不能愉快的玩游戏,投诉就会满天飞,论坛就被报障的帖子刷爆了,由于对于不少用户来讲,不上微信可能问题不大,但要是几小时不能玩游戏,那就要爆粗口了。如何保证游戏接入系统的高可用,让用户可以愉快的玩游戏,成为了咱们的一个巨大的挑战。缓存

为了实现游戏接入业务的高可用,咱们跳出传统的面向系统的高可用的思路,转而从业务的角度来总体考虑高可用,最终实现了一套“立体化的高可用架构”。接下来我将逐一展现这套立体化高可用架构的一些具体实践。服务器

1、面向业务的高可用目标

业界高可用的通用指标是几个9,例如5个9表明一年业务不可用的时间是5分钟,4个9表明一年业务的不可用时间是50分钟。咱们最初也是使用这个指标来做为咱们高可用的目标,可是在实际的操做和讨论过程当中,发现这几个指标虽然简单,可是并不能直观的理解,并且对于咱们分析问题和设计方案没有很强的指导意义,所以咱们决定找更加容易理解和操做的目标。微信

但提及来容易作起来难,高可用自己就是一个主观色彩比较强的概念,不一样的人理解都不一致,要肯定一个更加容易理解和操做、你们又能达成一致意见的目标,居然成了咱们首要面对的难题。咱们前后讨论了屡次,先后使用了“提升可用性”、“具有XX能力”、“解决存在的可用性问题”……等多个目标,但这些目标最后都被否决了,主要缘由就是咱们的BOSS认为这些都 无法量化,无法评估,不能认为作了事情就必定可以达到目标。当时研发团队和BOSS还有一点小分歧:研发团队认为除了几个9外,高可用无法量化;而BOSS认为一切均可以量化,只是咱们还没找到方法。不得已,团队又继续头脑风暴,功夫不负有心人,终于在一次讨论中想出了一个可量化可衡量的高可用目标: 3分钟定位问题、5分钟恢复业务、平均最多2个月发生一次问题 ,这样计算下来一年不可用的时间大约就是50分钟,正好契合4个9的业界通用的可用性目标。网络

在后来的项目执行过程当中,咱们发现这个目标真的是很是有用,很是具备指导意义,具体表现为:session

  1. 目标聚焦于业务,而不是聚焦于技术,确保最终效果不会走偏
  2. 将目标自顶向下分解,很容易就得出要作的事情了
  3. 设计和讨论方案时,目标就是一根准绳,是否可行,拿这个目标一衡量就很清晰了

后来的项目总结时,咱们都认为这个目标是项目成功的第一关键。

2、立体化的高可用架构设计

将咱们的高可用目标分解一下,其实有3个子目标: 

1. 尽可能避免发生问题

不出问题固然是高可用的首要目标了,否则的话每天出问题,处理再快也没意义。 

2. 快速定位问题

出了问题要可以快速发现和定位,不要报警或者用户投诉过来后还要花半天才能定位问题,在问题发生后尽快定位初步的缘由所在,尽快处理问题,防止问题恶化。 

3. 快速恢复业务

特别注意这里咱们强调的是“恢复业务”,而不是“解决问题”。不少人在处理生产问题或者故障的时候有一个误区:那就是必定要找到问题根因,而后解决。实际上大部分的时候这样作都很难的,也很耗费时间。好比说某个机器响应很慢,可能的缘由有:机器磁盘有问题、机器的CPU被耗光了、这台机器上的程序陷入死循环、jvm垃圾回收时间较长......要在短短几分钟内排查这么多可能的缘由是很难的,但咱们不知道真正的缘由也能够恢复业务,好比说最简单的是直接把这台机器马上下线,让流量分配到其它的机器。

当咱们审视这3个目标的时候,就会发现没有哪一个系统的架构可以独立的知足这目标,必须从业务的角度全方位、立体化的来分析和设计高可用方案。结合咱们的业务,最终的架构实现方案如图1所示。

经过这个图咱们能够看到,这个架构设计方案并非传统意义上的软件架构,而是一个高可用的业务架构,真正和传统系统架构相关的就只有“异地多活”,其它的功能或者系统并不属于狭义上的架构设计范畴,但这些功能和系统组合起来,共同保障了业务的总体高可用。

3、客户端重试 + HTTP-DNS

当咱们的业务发生问题的时候,用户侧确定是感知最快的,若是可以在用户侧感知并马上处理,问题的影响将大大下降。用户侧最简单的处理问题就是重试,当遇到某些错误的时候用户侧再重试一次,错误能够是通用的错误,例如HTTP 404/500,也能够是业务上的错误码,只须要客户端和服务端预先约定便可。

用户侧重试是处理问题速度是最快的,但一个最大的问题就是DNS的不可靠性。简单来讲,若是经过DNS拿到了错误的主机地址,即便重试也同样一样是错误的。致使DNS错误的缘由主要有以下几种:

1. 用户侧DNS被劫持,hosts被篡改

以下是咱们的域名在用户机器上被篡改的实例,能够看到咱们的域名被篡改为了127.0.0.1。

 

2. 缓存DNS服务器污染,返回客户端错误IP

2014年1月21日下午3点,国内顶级域的根服务器出现异常,许多知名网站的域名均被劫持到一个错误的IP地址上,至少有2/3的国内网站受到影响,用户没法正常访问。根服务器恢复后,因为DNS缓存问题,部分地区用户“断网”现象仍持续了几个小时。 

3. DNS缓存时间较长,短则10分钟,长则几小时

DNS的解析机制为了提高效率,在不少地方会有缓存,例如本机的缓存,DNS服务器上的缓存。缓存带来了效率上的提高,但同时却给故障处理带来了不小的麻烦,即:当咱们将故障的机器下线或者将DNS指向的主机地址修改之后,用户并不能马上感知新的主机地址,在缓存有效期内仍是会继续访问旧的主机。

DNS的这几个问题虽然咱们都很清楚,可是也无能为力,由于咱们不能控制DNS的设备,也不能修改DNS的实现机制。要想解决这个问题,只能另想办法,咱们的解决方案就是HTTP-DNS。

故名思议,HTTP-DNS就是经过HTTP的方式来本身实现一套DNS的功能,简单来讲就是客户端经过HTTP接口来获取指定域名对应的主机地址,而再也不经过传统的DNS设备来获取主机地址。相比传统DNS,HTTP-DNS具有以下优点: 

1. 本身实现,控制力度强,能够根据业务特色灵活实现

能够根据业务进行细粒度的调度,例如发现A业务某个集群请求量较多,能够动态的将请求分配到其它集群。 

2. 更新快,故障处理及时

当更新域名对应的主机信息后,客户端可以马上拿到最新的信息。例以下线一台机器后,客户端再来获取主机地址就不会获取已经下线的机器地址,可以实现秒级的故障处理速度。

固然,HTTP-DNS的这些优点是在特定场景下才能体现的,并不能彻底取代传统的DNS。由于若是每次访问都先经过HTTP-DNS拿取主机地址的话,效率和性能都过低,对于手机类智能设备还会致使耗电和流量增长。所以咱们须要结合传统DNS和HTTP-DNS的优点,既要保证大部分状况下的性能和效率,也要保证异常状况下的故障快速处理。

具体的作法为:正常状况下咱们经过传统DNS完成业务请求,异常重试的时候经过HTTP-DNS完成请求。如图3所示简要的说明了总体流程。

 

4、功能分离 + 功能降级

咱们的高可用目标中,首要的目标就是“尽可能避免发生问题”,但对于如何避免发生问题,刚开始的时候团队并无明确的方向,有的同窗从项目管理角度提出“结对编程”、“上线评审”等流程保障机制;也有同窗从测试角度提出“增强测试力度”、“自动化测试”等测试手段;咱们甚至还想到了“提高人员水平”这些人力资源措施......但这些措施都强依赖于人的因素,而人的因素每每是最不可控的,相比之下,咱们认为经过技术的手段是更可控的,因此制定了“技术驱动”的总体策略。

经过对系统业务的仔细分析,以及对过往线上故障的问题的分析,咱们制定了“功能分离 + 功能降级”的方案,具体解释以下; 

1. 功能分离:划分核心功能和非核心功能,将核心功能和非核心功能物理隔离

这里有两个关键点:

  • 首先要区分核心功能和非核心功能。例如咱们的游戏接入业务中,登陆、注册、校验是核心功能,消息推送、日志上报等是非核心功能。核心功能是用户玩游戏必须的,核心功能一旦有问题,玩家就不能玩游戏了;而非核心功能即便有问题,暂时也不会马上影响玩家玩游戏,而每每非核心功能的变更反而比较频繁。所以,优先保证核心功能正常,是咱们首要的目标。
  • 其次是物理隔离。包括数据库、服务器、缓存等都要隔离,由于只要核心功能和非核心功能存在共享的资源,就有可能由于非核心功能影响核心功能。举个最简单的例子,若是数据库共用一套,那么非核心功能若是出现了大量的整表查询,核心功能一样受到影响。

总体的架构示意见图4。

 

2. 功能降级:当出现故障的时候,能够将非核心功能直接降级,保护核心功能不受影响

拆分为核心功能和非核心功能后,虽然物理上二者隔离了,但有的业务仍是须要核心功能和非核心功能配合才能完成,这就存在了必定的风险。好比说消息下发(非核心功能)须要获取用户的信息(核心功能),若是大量消息下发的话,就会给核心业务系统产生较大的压力。这种状况下咱们能够经过将非核心功能停掉,以保证核心功能不受影响。

将某个功能停掉的传统方式就是打patch,但作过的同窗都知道,这样作的效率过低了:研发改代码、测试验证、运维部署,一路走下来,至少1小时以上,还容易出错,并且过后还要打另一个patch恢复功能。为了实现“5分钟恢复业务”的目标,咱们开发了一个后台管理程序,当须要停用某个功能的时候,只须要在后台上点击一个按钮就可以完成,花费时间只须要几秒钟。

5、异地多活

一般咱们讲系统架构的时候,异地多活每每都是最吸引人的,由于异地多活看起来很美好,一个机房故障,其它机房可以彻底接管业务,故障处理简单快速。但异地多活每每实现都是很复杂的,其复杂性不是体如今业务处理层面,而是体如今数据处理层面。简单来讲:异地多活须要保证数据的一致性和实时性,但异地机房间的距离自然决定了了数据的一致性和实时性是没法保证的。

目前业界常见的异地多活方案整体上能够分为两种: 

1. 跨城多机房

在不一样的城市搭建多个机房,机房间经过网络进行数据复制(例如MySQL主备复制),但因为跨城网络时延的问题,业务上须要作必定的妥协和兼容,不须要数据的实时强一致性,保证最终一致性。

例如微博类产品,B用户关注了A用户,A用户在北京机房发布了一条微博,B在广州机房不须要马上看到A用户发的微博,等10分钟看到也能够。

这种方式实现简单,但和业务有很强的相关性,例如微博能够这样作,支付宝就不能这样作。 

2. 同城多机房

同一个城市多个机房,距离不会太远,能够投入重金,搭建私有的高速网络,基本上可以作到和同机房同样的效果。

这种方式对业务影响很小,但投入较大,若是不是土豪公司,通常是承受不起的;并且遇到极端的地震、2013年汕头水灾这样天然灾害,同城多机房也是有很大风险的。

咱们暂时还不是土豪,因此同城多机房就无法用了。同时,游戏接入数据还要求实时强一致性,例如A用户在北京机房注册成功了,而后到广州机房登陆游戏,要求可以马上登陆,不可能让用户等10分钟才能登陆,因此跨城多机房也不能用了。怎么办?方案彷佛陷入了僵局。

咱们转向了第三种方式:由业务层来控制数据的强一致性和最终一致性,而不是由数据层来控制数据强一致性和最终一致性。具体来讲就是3个手段: 

1. 异步分发

一个机房生成的数据,会经过程序异步分发到其它机房,机房间没有底层的数据复制通道,不存在主数据库和备数据库的概念,也就没有主机房和备机房的概念,每一个机房都不依赖其它机房就能够独立提供服务。

经过这种异步分发的方式,能够保证数据的最终一致性。当其中一个机房宕机时,除了宕机时刻尚未分发的数据外,其它数据在其它机房都已经有了,其它机房能够接管宕机的机房的业务。

与传统的MySQL复制相比,业务层数据分发能够更加灵活,咱们能够根据业务来选择真正须要分发的数据,或者在分发前作一些预处理操做。业务层分发性能也能够作到比MySQL更高,由于咱们能够并发的进行分发。 

2. 二次读取

异步分发只能保证数据的最终一致性,不能保证数据的实时一致性,所以咱们设计了业务层二次读取的机制。即:A机房读取不到用户的数据,则到B机房或者C机房去读取。注意这里的跨机房读取操做都是经过接口,而不是经过访问数据库完成的。

经过二次读取的方式,能够保证数据的实时一致性。 

3. 重复生成数据

对于全局惟一且又保证必须一致的数据,咱们不是依赖数据库的自增id,或者zookeeper的全局id之类的机制,而是经过算法生成,这样保证无论在哪一个机房均可以生成相同的数据。当其中一个机房宕机时,若是数据尚未分发到其它机房,此时虽然须要用户从新操做一次,但因为生成了相同的数据,业务上不会产生问题,用户可以继续正常使用业务。

而对于那些业务上能够重复生成的数据,例如session、ticket类数据,处理就更加简单了,不一样机房间都不须要同步此类数据,若是没有,直接二次生成便可。虽然要求用户多登陆一次会带来体验上的不友好,但咱们的核心目标是不影响用户玩游戏,相比咱们的核心目标来讲,这点影响微不足道。

在咱们最开始设计这套架构的时候,有的同窗忧虑地说“这也叫架构啊,看起来好像一点都不高大上哦”,但最后实现的效果大大超出了咱们的意料。经过上述三种手段,咱们实现了即便一个机房彻底宕机,另一个机房也能够接管所有业务的目标。自从有了这套异地多活的架构,运维作机房切换很是简单和轻松,有时候为了验证系统抗压能力,咱们在正常的时候也将某个机房的业务所有切换到另一个机房,甚至运维同窗能够开玩笑的说“没事作的时候切换一下玩玩也能够”!

6、立体化&自动化&可视化的监控

处理过线上问题的朋友可能都有这样的经历:客户投诉如今业务有问题,因而研发测试运维开始投入定位和分析问题,一场忙碌但又混乱的活动开始了。

A研发去查日志,可是线上机器好多,一台一台的看,1小时过去了;若是想把日志下载下来,一下几个G的文件,网速又慢,只能干等……

B研发同窗以为数据库可能有问题,可是本身又不能直接操做数据库,只能找DBA,可是DBA不在线啊,赶忙打电话,DBA说我正好休假呢……

C运维同窗更头大,一边要应付研发和测试的各类问题,一边还要本身查机器CPU、内存、io、网络、程序状态,并且还那么多机器。

这样的作法确定达不到“3分钟定位问题”的要求,怎么办呢?咱们的运维大神给出了“立体化、自动化、可视化监控”的方向:在故障发生的时候,定位问题的所须要的各类信息都已经准备好了,不须要再到各类各样的系统中去执行各类各样的命令了;并且这些信息都必须是可视化的,可以一目了然的看出问题所在。具体实现以下:

 

1. 立体化

立体化就是将故障分析和定位时涉及的全部的相关信息都要监控起来,共分为5层,具体各层和含义以下:

  • 业务层

收集和分析业务层的访问量、成功率等指标。例如当系统被刷的时候,业务层可以一目了然的看出访问量会增长不少

  • 应用服务层

应用服务层指的是以URI为维度的分析,能够看到某个URI的访问量、HTTP响应码分布、HTTP响应时间等指标。应用服务层与业务层并非一 一对应的关系,一个业务可能对应多个应用服务层的URI,一个URI也可能对应多个业务层的业务。

  • 接口调用层

接口调用层指的是系统依赖的外部系统接口,收集的信息包括访问状况,包括时延、错误码、次数等,当外部系统故障致使咱们的业务故障时,经过接口调用层就可以快速的定位具体问题。

  • 基础组件层

基础组件层指系统依赖的底层组件,例如容器、数据库、缓存、消息队列。不一样的组件收集的信息不同,例如数据库MySQL的监控指标包括链接数、请求数、查询行数、更新行数等,而缓存memcached包括使用率、踢出率、命中率等。

  • 基础设施层

基础设施层指操做系统状态、网络状态,收集的信息包括cpu使用率、内存使用率、网卡流量、链接数等。 

2. 自动化

自动化的含义就是不要再由人工去分析日志或者执行命令了,而是由程序自动完成这些动做。当故障定位的时候须要这些信息时,能够当即看到,节省故障定位时间。为此咱们开发了一套数据收集和分析系统,这套系统能够从其它各个系统(包括业务系统、运维系统等)获取并分析数据,例如日志数据、状态数据等。

数据自动化收集和分析系统的结构以下:

其中Logstash用于采集日志,redis用于缓存日志,elasticsearch用于存储和分析日志。 

3. 可视化

可视化的含义就是故障定位所须要的信息可以经过图表和数字直观的展现出来。有了自动化的收集和分析做为基础,可视化只须要将数据作成图表展现便可。除此之外,同比、环比这类数据也能够经过系统直观的展现出来,方便快速判断问题所在。

 

7、总结

咱们来回顾一下整个这套架构方案是如何实现咱们最初的目标的:

  • 3分钟定位问题

经过运维已有的拨测脚本,加上立体化&自动化&可视化的监控,绝大部分故障可以在3分钟内发现并定位初步的缘由。例如是由于访问量暴涨,仍是数据库变慢了,仍是网络被SYN FLOOD攻击了。

  • 5分钟恢复业务

若是是某台机器或者某几台机器故障,咱们能够将故障机器下线;

某个接口或者某些业务故障,若是不是核心业务,咱们能够采用功能降级快速处理;

若是是大面积的业务故障,甚至是核心功能也故障了,咱们能够经过将故障机房的业务切换到其它机房;

若是是全部的机房核心业务都出故障了,那就只能具体问题具体处理了,例如若是是新版本引发的,首先马上回滚版本;若是是被攻击了,须要采用防攻击手段等。

  • 平均最多2个月发生一次故障

经过核心功能和非核心功能分离,可以尽最大可能的保护核心功能的可靠性。固然除了这个措施外,咱们还有其它更多常规的保证措施,例如项目流程上的部署评审,自动化测试,灰度发布,tcpcopy环境预发布、MySQL高可用、Memcached高可用等措施。

架构设计主要参与的人员有:王金银、王力志、聂勇、詹青朋、李运华、李俊,整个项目获得了研发BOSS郑从威的大力支持,这也是项目成功的关键因素!

 


做者简介:李运华,目前就任于阿里巴巴集团移动事业群,担任资深软件工程师,主要从过后台架构设计、开发工做,同时带领团队负责部门的公共组件设计和开发。热爱技术但不拘泥于技术,爱好分享,喜欢读书,技术控、读书狂。 
相关文章
相关标签/搜索