二、黄金眼架构演进
黄金眼为阿里妈妈业务保驾护航已久,这里以最初的版本为起点来阐述黄金眼架构的变迁。架构和业务是均衡发展的,业务的规模驱动着架构的演进,架构的变迁能够为业务灵活扩展提供稳定的支撑。
下文中所讲的三种架构版本的演进过程,是我们保持业务发展、系统性能和工作效率之间平衡的过程。反推这个过程,新的架构也适合之前的业务规模和场景,然而衡量一个架构的优劣不是兼容了历史,而是能预见未来。所以,我们在保持业务和技术均衡的基础上,结合对未来业务潜在的需求的思考,才产生了每一次架构的改进和升级。这些是黄金眼每位成员的集体智慧,供大家参考学习。
• 应用:构建在整个黄金眼之上,对外部用户提供各种有针对性的服务,包括监控报警服务,预测服务,故障定位服务,算法A/B test服务等。
• 实时计算:黄金眼中95%以上的业务线指标数据都是通过实时计算得到的,需要监控报警的数据更是全部由实时计算storm平台解析,处理,汇聚之后写入分布式存储当中,供给前台展现报警。
• 存储: HBase集群在整个黄金眼中是集数据存储、展现的数据中心,所有的实时计算结果数据、阈值数据、其他时间序列的数据都要汇总到HBase存储当中
• 离线计算:离线计算部分主要处理的是离线的数据表,用于每天的日报,周报,反作弊数据统计,也是之前比较传统的统计报警模式。离线计算一般是以天为单位,可以优化到小时级别,但仍然存在报警晚等问题。
1、Goldeneye架构V1版本——storm模式
这一阶段的业务特点就是野蛮生长,业务每天都会迸发出新的玩法,线上流量也在逐步突破历史最高。当线上出现问题需要排除查的时候,对几十亿级别的流量的线上系统故障维持1小时,损失是不可估量的。而业务还大部分依赖于离线计算,即使优化到小时级别,也很难减少损失。因此我们改变之前依靠离线报表进行监控报警的方式,引入storm实时计算引擎开发我们的监控报警任务。根据原始的storm语义,结合当时的大盘数据sum的需求,我们设计了第一版黄金眼实时计算的架构。对于每一个独立的业务线都定制一个独立的storm任务,每个实时任务的框架图如下所示。
Spout阶段
该阶段主要和消息中间件进行通信,读取对应的实时日志消息,维护读取的时间戳保证数据的exactly once。阿里内部使用的Time Tunnel作为实时的中间件,功能类似开源的kafka。根据大盘监控的统计需求,组合对应的key(例如广告位+时间戳进行组合)、value(例如pv数量)信息,发送给下游的bolt。
Count Bolt阶段
使用filed grouping方式,相同的key在同一个bolt中处理。在count bolt内部,先进行初步的内存聚合,然后根据批量batch的条目数或者batch时间触发emit发送给下一级的write bolt。
Write bolt阶段
write bolt阶段有两种模式,根绝数据量的情况选择Put模式或increment模式。put模式采用先get在put的方式对数据进行更新,increment模式直接发送给HBase,让HBase内部的region server进行累计。
通过这一版本的改造,我们的计算周期从小时级别缩短到秒级别,报警周期缩短到5分钟报警。在报警策略方面,我们也摆脱了人工拍定阈值的方式,采用同环比阈值报警,提高了报警的准确性。
Goldeneye V1的优势很明显,每个业务线单独开发逻辑,部署任务,业务逻辑清晰。不足也是比较明显,需要开发同学对storm编程比较熟悉。进行双11、双12等大促活动时,需要针对各自的业务进行逻辑的调整,资源扩容等工作。而且每个业务都需要重复开发外围的TT/HBase代码,抽象封装可以大大减少重复代码量。大盘需求得到满足,而更细粒度的监控需求需要定制开发,定制开发难度大、周期长。
2、Goldeneye架构V2版本——ARM框架
黄金眼大盘监控的效果很好,于是其他业务线也找到了各自的技术团队,生产了一台给自己业务线使用的Goldeneye V1。那个时期各业务线终于过上了美好而又和谐的生活。(直到机器老化了,业务线同学觉得自己维护起来很费劲,而且业务整合的时候跨业务线数据不能打通,这就是V2架构的背景)。
技术方面,用户重复计算这些场景,对于storm的理解不够深入、实时任务性能不够,所以也急需要我们改善用户的编程习惯和编程体验。让用户只关注业务逻辑本身就可以。于是我们开始着手抽象实时计算框架了。我们在storm的原语上抽象了ARM(Alimama Realtime Model)是广告实时框架的简称,它是包含输入、输出、存储以及实时计算框架的组件集合。
ARM提供如下组件:
• 输入输出:输入输出包括TT, HDFS, ODPS及MetaQ/Swift等。通过配置实例化组件,API访问。
• 存储:支持对LDB, MDB, HBase的访问,通过配置实例化组件,通过API访问。
• mapmerge:mapmerge框架抽象出map-merge计算框架,帮助用户实现KV流的实时计算。
Mapper阶段
用户只需要关心日志解析的代码,无需在关心与外部TT/HBase的链接配置等操作。核心代码就是将一条原始的raw log,解析成对应的结构。其中一条日志可以输出多条组合向后发送。</KEY, VALUE></KEY, VALUE>
Merger阶段
用户只需要关心真正的内存count逻辑,关心用户代码即可,不需关心外部存储的配置等信息,在需要输出的时候直接调用write(key, value)即可。
在V2版本用户只需要关心解析包和业务的聚合逻辑,已经不需要在关心外围设备,以及集群相关的配置信息了,这样大大解放了用户的生产力,使得各个业务线可以在ARM平台上快速构建实时监控任务。不足之处是每个业务独立的存储结构,每次都需要独立开发一条web展示系统,同时考虑到大部分的需求是Sum,分布式sum操作可以进一步抽象,而且我们在实践中又发现了类似join、TopN等需要抽象的实时语义,需要进一步的完善。
3、Goldeneye架构V3版本——ARM算子层
这一阶段的业务特点就是黄金眼在阿里妈妈内部已经覆盖了所有的核心业务线。对于其他业务线的需求,需要给非技术同学提供更易用性的接入,为外部引流部门提供高性能的解决方案,为已经在系统上运行的部门提供快速、可配置的聚合逻辑。
颠覆之前的开发模式,真正走向平台化,在完整兼顾阿里妈妈内部需求的同时给集团内部的其他部门提供平台化服务。ARM算子层在ARM框架mapper/merger接口之上,封装了实时sum、实时join等多种计算模型。
Source阶段
和goldeneye V2 mapper的相同之处在于,用户只需要关心具体的解析逻辑。和goldeney V2 mapper不同的是,之前用户会把数据转换为结构,例如key=a, key=b, key= c,需要对下游发送3条数据,而在新版本中用户仅需要发送一条的流</KEY1, KEY2, KEY3, VALUE></KEY, VALUE>
aggregator阶段
在这个阶段相比goldeneye V2有了本质的提高。用户不需要关心cache buffer等代码的配置,只需要在配置文件中书写类SQL的配置就可以。ARM算子层会把这个SQL语句转换成对应的执行计划,映射到具体的计算模型上。例如:
经过这几个版本的迭代,ARM框架已经很趋于成熟,在storm平台之上,构建一套完整的分布式计算sum,分布式join, topn , unique等功能。同时随着框架的引进我们也接入了更多的业务,覆盖了阿里妈妈90%以上的业务线,同时我们还对外在阿里集团内部和多个部门合作共建,努力推广黄金眼监控系统。我们的优势其实很明显,我们在监控上做到准确无误,用户的接入效率也提高了10倍以上,而且用户在后期的监控需求变更上也非常方便,易于维护。经过算子层的抽象,用户只需要关心解析内容和简单的SQL配置就可以完成实时聚合了,这大大提高了使用的易用性,接入效率提高10倍以上。同时在这个阶段我们对后台的算子层也进行了深入的优化,在性能生也有很大的提高,峰值流量QPS可以覆盖300W/s,完美的度过了2016年双11的流量高峰,以及外部媒体流量引入的高峰。技术优化点在接下来详细阐述。