BT

如何利用碎片时间提升技术认知与能力? 点击获取答案

如何基于AWS的基础设施构建高可用、高可扩展的系统

| 作者 汪磊 关注 0 他的粉丝 发布于 2017年12月5日. 估计阅读时间: 20 分钟 | QCon北京2018全面起航:开启与Netflix、微软、ThoughtWorks等公司的技术创新之路!

亲爱的读者:我们最近添加了一些个人消息定制功能,您只需选择感兴趣的技术主题,即可获取重要资讯的邮件和网页通知

各位晚上好,首先感谢大家抽空参与我的这次主题分享,同时也感谢 InfoQ AI 前线组织这次瀚思科技主题月!

瀚思成立于 2014 年,属于 To B 的安全行业。我们主要为企业用户构建基于大数据的安全分析平台,通过大规模采集企业的各类安全数据,并运用各种规则引擎、机器学习算法,在海量数据里挖掘出隐藏的安全问题,最终的目的是构建企业里基于数据的安全大脑,用数据驱动安全。

今天是瀚思科技的主题分享月里的第二期。上周我们的首席科学家万晓川分享的重点,是在于构建一套大数据分析平台时,各种技术选型上的主要备选方案,考虑因素以及关键决策等方面。今天我的分享重点,是如何在支持弹性计算的云平台如 AWS 上构建一套高可用性和高可扩展性的大数据分析平台。和上期一样,我也不会介绍安全方面的内容,更多的是大数据平台技术落地上的工程化实践经验,包括如何设计,如何规划,如何监控。其中会拿机器学习算法分析模块举例如何设计高可扩展性,但是会弱化机器学习算法本身的特性,优化,应用场景等方面。后续的两个分享会有更多这方面的内容。

一定有人会问到,为什么要在云平台上构建安全分析平台。这里有多方面的原因,首先瀚思有在线的安全分析服务“安全易”。其次,瀚思自己有很多的安全数据需要处理,比如全球威胁情报。自己构建数据中心来支持这样的运算服务对于初创公司来讲,upfront cost 有点高,选用 AWS 这样的平台,即开即用,按需付费是很合适的模式。

也一定有人会问到,那为什么选择 AWS。瀚思的研发团队,在创业之前,从 2011 年开始就在 AWS 上大规模构建在线的安全扫描服务,算是国内最早接触 AWS 平台的团队之一。然后,瀚思有全球部署安全分析触点的需求,AWS 的数据中心的全球覆盖率是最好的。从 Gartner 的 MQ 来看,AWS 也是公有云市场上 leader 中的 leader,远超其他竞争对手。

这是 Gartner 2017 年公有云市场的 Magic Quadrant,可以看到 AWS 依然遥遥领先。

前面一张图是上周万晓川的分享中举例的一个典型的大数据分析平台的架构。简单来讲,这样的典型平台里数据的处理流程是:采集 -> 存储 -> 分析 -> 展现。其中存储和分析是一个迭代完成的过程,分析的结果会进入存储,也会再次被用作分析。最终所有的数据,无论采集的原始数据还是分析加工出来的数据,都会通过数据可视化的技术来展现给用户。

采集 -> 存储 -> 分析 -> 展现,这样的数据流程里,采集、分析、展现一般都分类为应用服务器的范畴,通过特定的代码逻辑来解决数据处理的某一个环节。而存储则很明显属于存储服务器的范畴,包括传统的关系型数据库,以及 NoSQL 数据库,其他的集群存储等。

构建大数据分析平台,一般会采用非常多的开源组件,这一点很常见。但是开源组件,一般很少有原生对 SaaS 部署方式的内建设计支持。这样将大数据分析平台 SaaS 化时,就会遇到很多难点,这里列举了 4 点。其中多租户和访问控制,是基于开源模块构建对客户的 SaaS 服务时的常见问题,比如 ELK 框架如何 SaaS 化。针对这两点,我在去年 AWS Summit 北京站有一个专题分享,有兴趣的同学可以关注瀚思的公众号,在去年 9 月的公众号文章里有相关的内容介绍。

今天主要讨论“高可扩展性”和“高可用性”这两个话题。针对存储服务器,这两点通常用集群 + 数据冗余 + 数据备份解决,每一类存储服务都有比较完整的方案。因此今天主要围绕应用服务器来谈这两个问题。

高可拓展性设计

首先,我们来谈谈高可扩展性设计

Auto Scaling Group (ASG) 是 AWS 平台为高可扩展性提供的基础服务之一。ASG 可以通过 Group 内服务器平均 CPU 负载、进出带宽或者应用程序自定义的指标来控制 Group 内服务器数量的动态增长或者削减。比如:当集群平均 CPU 负载超过阈值,ASG 开始基于 AMI 创建更多的 EC2 服务器加入 ASG 来分担工作,直到 CPU 平均负载降到阈值内。

有了 ASG 为基础,可以创建出一个充分利用弹性计算平台特性的高可扩展性应用服务器集群。但是从 AMI 随时创建一个新服务器加入集群即开始分担工作,或者随时削减一台服务器,不影响整体集群的计算任务,对应用服务器设计有一个很高的要求:无状态。

无状态(stateless) 这个词,相信很多人可能听过。关于无状态的应用服务器设计要素,这里是我个人经验总结的两点:1)单个应用服务器的可更替性,2)应用集群里任意服务器的对等可替换性,其中前者是后者的基础。接下来分别详细解释。

首先是单个应用服务器的可更替性。主要考虑的是集群里某台服务器由于某种原因挂掉(比如手抖了一下敲错脚本),ASG 恢复一台服务器后,可以达到这台服务器被更替前同样的状态。不会由于服务器的更替,导致新服务器程序逻辑不一致,数据丢失,不可恢复,应用逻辑中断,集群作为整体的计算状态出现错误等状态。

为达到这种可更替状态,主要考虑的是数据与应用分离,以及妥善处理好当前正在执行的任务的状态。这页 slides 细分了数据与应用分离的几个主要考虑方面。数据与应用分离,也是对无状态设计的最常规理解。

在单个服务器可更替的基础上,更进一步的无状态设计要求,是集群里的任意服务器之间的对等可替换性。主要意思是服务器上的计算任务可以自动无缝迁移到其他服务器,不依赖于本机的上下文或者历史执行状态。有了这一层保证,才能在 ASG 根据策略动态增加或者削减服务器数量时,整个应用服务器集群的工作任务可以动态负载到变化过后的服务器,实现高可扩展性。这里列举了几个常见的对等可替换性设计的制约因素。

不同的应用服务器的无状态设计要求与思路是不一样的。前面列举的采集、分析、展现三类大数据分析平台相关的应用中,分析应用是最难做到无状态的,因为他往往涉及数据上下文依赖,从而不满足“对等可替换性”。这里我们以一个无监督机器学习算法“时间序列异常”分析为例,分析一下这样一个算法类的分析应用服务集群,如何满足无状态设计的两点要求。

这个是我们产品的时间序列异常分析算法的执行结果界面的截图。我们的时间序列异常检测算法通过无监督机器学习的方法,基于历史数据训练找到数据指标中的异常点,比如图中的红点。在这样一个算法执行任务集群上,可能运行有非常多的并行算法分析任务,这样一个看起来对数据前后关系有强上下文依赖的算法应用集群,如何做到无状态设计呢?

无状态设计的主要思路,是将应用服务的主要逻辑分解成多个子任务或子步骤,直到子任务可以被整体状态迁移。时间序列异常检测算法的执行过程,常规来讲有两个步骤:

第一,通过 ETL 过程梳理待分析的数据,得到算法输入所需的(time,value)形态的基于时间序列的数据流;

第二,将分析周期内的时间序列数据输入算法逻辑,计算出异常点。

因此时间序列异常分析集群的工作,是两个子步骤的循环任务。且一个集群会在同一时刻并行运行很多的算法分析任务。每个算法分析任务的子任务,需要能够动态的负载到任一台服务器上,分析处理好这两个子任务的状态迁移,就完成了设计目标。

这两个任务本身的特性非常类似,我们以数据 ETL 处理步骤为例进行设计说明。比如我们需要算 1 分钟步长内每笔数据里 bytes 字段的 sum 值,即 1 分钟为单位的数据传输量。这样的 ETL 结果输入给时间序列异常算法,可以找到数据传输量这个分析目标的异常波动。这里每 1 分钟的聚合计算就是一个子任务单元。

这个 ETL 子任务,首先要解决服务的可更替性。参照前面的设计考虑点,获取的数据源,输出的数据结果,应该部署在外部的数据队列集群或者存储集群,做到数据与应用分离。当前算法任务的 ETL 具体设置,应存储在策略服务器,做到配置与应用分离。当前 ETL 任务的执行状态(未启动,运行中,已完成),应该标记在外部存储。到此,任何一个 1 分钟的 ETL 单元,如果计算到一半服务或者服务器出错退出,可以有替代服务重新完成这个 ETL 单元。

第二步是解决对等可替换性,即任何一个算法任务的任何一次 ETL 步骤单元,可以由集群里任意一台服务器完成,实现子任务的可迁移。

首先将 ETL 任务预标记出来,存储在外部存储比如数据库。这个步骤可以由集群里每台服务器都尝试为集群要处理的每个算法任务标记出下一个 ETL 计算任务,通过算法任务 ID+ 计算起始时间戳为主键来保证任务的唯一性,并将任务标记为 waiting 状态。

接下来每个服务器可以竞争任务列表里的下一个 waiting 任务,这里可以用类似选举算法来决定谁取到下一个任务。一旦决定,即为任务打上 running 状态标记及开始时间。这个期间,其他服务器不会争取 running 状态的任务,ETL 计算完成则标记为 Done 状态。计算过程中,一旦服务器或者应用崩溃,或者由于 ASG 主动削减一台服务器,导致此服务器负责的任务未结束一直是“ongoing”状态,在下一轮任务选举过程中,需要对所有 ongoing 任务做超时检测,一旦超时,则重新标记为 waiting 状态,重新进入选举列表。

通过将子任务的状态外迁到存储服务器,以及任务的选举分配 + 超时检查,完成了 ETL 计算任务在集群内的对等可替换性。即任何任务可以运行在任何服务器上,没有前序或者后序的状态依赖。

至此,ETL 计算任务实现了无状态设计。以此类推的完成算法计算子任务的无状态设计,这样任何一个算法任务的任何一次子任务,可以运行在集群任何一台服务器上,则整个时间序列异常算法分析应用服务器实现了无状态。接下来可以在 ASG 的控制下,通过集群的平均 CPU 负载来动态水平扩展或者缩减服务器数量,完成了集群的高可扩展性。

这里举例的只是一种应用场景的设计思路,并不能解决所有的应用服务器的场景,需要对不同的应用逻辑针对性设计,No Silver Bullet。

高可用性设计

接下来,我们来谈谈高可用性设计。

一个大型 SaaS 系统的高可用性(High Availability,简称 HA)是一个比较复杂的系统工程,不是一两个简单技术点的应用就可以解决,也很难通过十几分钟的 Session 来讲清楚。我在这里试图把我从过往经验中看到的各种方法和实践,通过一定的层次结构整理出来供大家参考。

从大的方面来讲,决定系统的 HA,主要决定因素有两个方面:设计与监控。设计在架构与技术思路上提高系统的 SLA,监控在止损思路上防止降低 SLA。

这张图 Highlight 了所有在高可用性设计中经常会被提及的关键词,非常多也非常离散。不过大家可能会发现,其中很多关键词,在刚才我们讨论高可扩展性的时候都有涉及到。这很正常,因为一个弹性可扩展的应用集群,其中每台服务器都有对等可替换性时,就相当于实现了 Active-Active 互备,AA 本身就是一种经典的高可用性设计方案。不过 AA 局限于服务器与应用程序层面,一个完整的全系统高可用性设计涉及 5 个层面:基础设施、服务器、应用程序、系统服务、区域。

这里,我们把刚才离散的所有 HA 设计关键词,按照这 5 个层面做了一个分类,让各位在做 HA 设计时有一个更清晰的结构化考虑思路。接下来我们对每一个主要的设计要点做详细的解释。后面的 slides 本身就是建议和 best practice 的合集,文字较多,我的附加解释会稍微少一些。

我们在前面介绍高可扩展性设计的服务可更替性时,已经介绍过数据与应用服务分离的概念。

理想的情况是 SaaS 系统的每一个应用角色都没有单点。现实情况下,对业务连续性的关键路径上解决单点基本上就可以。一些非关键路径,非实时任务的应用,在这一点上可以有妥协。

这里再次 recall 一下无状态设计的两个方面,这是 HA 和 HS 的核心理念。

异地多活是一个非常复杂和庞大的话题,我们只在一定程度上做了小规模的尝试,这里列出的是一些可能的方法和思路。一个超大型的 SaaS 系统 + 超高负荷情况下的异地多活方案遇到的问题要远比我这里列出的复杂。

在我们有了五个层面的完备的高可用性设计,且完全落地后,为什么我们还需要监控?理由有很多,最基础的一个:bug 永远有。。。

从我的个人经验来看,监控的核心诉求,是“比客户更早发现问题”,或者我们通常讲的“第一时间发现问题”

我之前负责的一个 SaaS 系统,曾经出现过一个 bug:在极端条件下,缓存系统的 sdk 的多线程 bug 被触发,导致 A 客户的配置策略应用到 B 客户的数据上。但是我们的系统本身运行状态一切正常,我们既有的常规监控也一切 OK。但是在系统服务层级,我们 SaaS 给客户的服务逻辑上已经是不可用了。由于客户自己从怀疑到确认,从 Level1 技术支持一直 escalate 到研发,事情已经发生一星期了,从开始少量客户被影响,到我们知道时已经是全球所有数据中心的大规模灾难了。事后分析发现,缓存错误出现时,各个系统的日志里的 warning,error log 显著增加,不过当时我们并没有对系统日志做很好的监控。如果这部分监控到位,应该缓存产生错乱的第一天我们就能够捕捉到。

这次事件之后,我们重新梳理了我们的监控思路,体系化的规划了整体的监控方案,和 HA 的设计类似,从底层平台到高层应用服务,做了全面的监控。这里是一个典型的利用了 AWS 平台很多特性以及很多外围系统实现的一个全面监控框架。

到这里,通过设计提升和监控止损,基本上可以保证一个大型 SaaS 系统的整体高可用性。我们的系统在多番改造后,连续几年做到了 SLA 100%,包括系统发布升级过程中也没有任何业务中断,不过这里需要结合很多 DevOps 和持续发布的最佳实践来支撑,这就是另一个话题了。

问答环节

Q1: 关于无状态服务的设计,比如您局的 ELT 的例子。可否采用 SQS+Lambda 来实现?

A: 是可以的,不过我们并没有做过 Lambda 上的尝试,按照我的的理解,是可以实现的。

Q2: 请问时间序列异常检测用的是什么无监督算法?请问对待时间序列中的周期性抖动,有什么方法可以检测或判断的吗?

A: 算法这块不是我的专长,我们下一期的吴睿同学,是这方面的专家,我把这个问题传递给他。

Q3: 我想问一下,基于日志统计 UV 有没有能够做到在线分析的快速计算方法,比如用户在操作界面选择任意时间段,任意一种操作,统计对应的 UV 值,在较短时间内返回结果。

A: 这是优点类似又要马儿跑,又要马儿不吃草的问题了。任意时间段 + 任意操作,就很难有解了。常规的做法,还是对数据的冷热程度作区分,热数据尽可能预加载,甚至对常见处理需求预处理。

Q4: 请问对于并行计算中有数据依赖或任务交互的场景,是如何解决。

A: 这个问题有点抽象,如果依赖讲的是前后依赖,可以类似我刚才举例的 ETL 处理那样,将过程分成子阶段,每个子阶段变成一个可迁移的单元。我们遇到过另一种比较难处理的情况是不同属性(或者用户)的数据混杂在一个数据源里产生,但是分析过程必须按同属性(或同用户)来处理。我们有一个利用数据转换状态的设计,有点长。我要表达的意思是,还是要看具体场景来分析。

Q5:UV 需要去重,计算量很大,用户任意指定时间段又没有办法预计算,这个是我们遇到到问题,如何解决?

A:这个问题和刚才那个任意时间 + 任意操作的问题类似,就不回答了

Q6:算法分步设计有什么好的实践建议?2. 有没有数据倾斜导致计算倾斜情况,如何避免?

A:算法领域我不太熟悉,我擅长的是大型系统的设计和工程化落地。关于算法的分部设计和数据质量导致算法结果有效性这类的问题,强烈建议感兴趣的同学参加下一期的分享。瀚思的算法专家同学会给出更好的回答。

Q7: 请问可以分享 PPT 么

A: 关注 AI 前线公众号,并在后台回复“汪磊”即可获得讲师分享的 PPT。

讲师介绍

汪磊,瀚思科技研发总监,12 年企业级安全产品开发经验,擅长大数据技术架构以及大规模 SaaS 服务架构,拥有两项美国专利,目前带领团队负责瀚思产品研发工作,曾任趋势科技资深项目经理、途牛旅游网研发总监职务,曾带领团队在 AWS 平台构建 SaaS 安全网关,直接与美国 Zscaler 竞争。

毕业于华中科技大学,获得软件理论硕士学位。

评价本文

专业度
风格

您好,朋友!

您需要 注册一个InfoQ账号 或者 才能进行评论。在您完成注册后还需要进行一些设置。

获得来自InfoQ的更多体验。

告诉我们您的想法

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我
社区评论

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

讨论

登陆InfoQ,与你最关心的话题互动。


找回密码....

Follow

关注你最喜爱的话题和作者

快速浏览网站内你所感兴趣话题的精选内容。

Like

内容自由定制

选择想要阅读的主题和喜爱的作者定制自己的新闻源。

Notifications

获取更新

设置通知机制以获取内容更新对您而言是否重要

BT