微博现在日活达到了 2 亿,微博广告是微博最重要且稳定的收入来源,没有之一,所以微博广告系统的稳定性是我们广告运维所有工作中的重中之重。
图片来自 Pexels
微博广告的运维主要负责资产管理、服务稳定性维护、故障应急处理以及成本控制等多个责任。
微博广告运维发展经历了如下阶段:从早期小规模的手工运维到工具化运维,随着服务器数量的发展,业务模型日渐发展,开发、运营、QA 都参与到产品的生命周期中,我们现在也进入了自动化运维的阶段,在新的虚拟化技术、算法技术的驱动下,我们也在朝着 AIOps 的方向努力。
在整个运维过程中,我们遇到了很多痛点,幸福的人生都是一样的,不幸的人生各有各的不幸,各家的运维都各有各的痛点。
我们的服务器在 3000 台以上,业务线及辅助资源各种各样,产品迭代非常快,且依赖关系复杂,流量变更,切换损失不可接受。
在这种情况下,我们面临资产管理困难、环境不统一、上线难度大、运维成本高的问题。
基于这些问题,微博广告运维工作主要集中在以下四个方面:
- 运维自动化
- 弹性计算
- 智能监控
- 服务治理
运维自动化
一个健全的自动化运维平台必须要具备如下几个功能:
- 基础监控
- 资源管理
- 事件集中分析
- 配置管理
- 批量运维工具
- 持续集成和发布
基于这些功能和需求,我们广告运维自主研发了 Kunkka 平台(微博广告运维自主研发的自动化运维平台)、资产管理、自动化上线等运维平台。
资产管理是基于公司 CMDB(公司级别的资产管理系统)获取到主机云服务器,针对微博广告对资源的管理需求自建定制化的资产管理平台。
配置中心包括服务注册、服务配置等功能;自动化上线涵盖了开发在上线过程中所需要的节点和流程。
自主终端是行业变化的功能实现,大家可以通过页面完成文件或命令下发、日志审计等各种工作。
Kunkka 基于主机和容器,通过 Salt 作为传输层进行命令下发,组件层包含开源软件,操作层将命令页面化,通过页面进行日常工作和管理。
这样的自动化运维平台基本上满足了运维的日常操作需求,在 Kunkka 平台中还有自动扩缩容的功能,我们针对这个功能进行延伸。
在自动扩所容的基础上,根据时间段,流量进行动态判断,自动决策的扩所容够功能。
弹性计算
为什么需要弹性计算
首先,在产品方面,我们的产品线很多,依赖关系比较复杂。
微博广告相当于一个桥梁,左边连接的是广告主,右边连接的是客户,需要将广告主的广告计划转化为用户的需求,让用户看到自己想要看的广告。
为了满足两边不同的需求,产品的变更和发布非常重要且频繁。
其次,在运营方面,很多有推广需求计划的大型活动都有临时扩容需要,比如 618 跟双十一,对于我们而言这两个活动带来了很大的冲击。
在 618 和双十一大促之前,为了加大自己的影响力,各个广告主会增加广告计划,微博广告这边再针对广告主的行为加大我们的曝光量,实现广告主广告计划的转化。
在 618 和双十一大促之前,为了加大自己的影响力,各个广告主会增加广告计划,微博广告这边再针对广告主的行为加大我们的曝光量,实现广告主广告计划的转化。
传统的业务运维
按照传统运维模式,扩容计划从立项到服务器上线,会经过诸多的流程跟漫长的等待。
从结果上来看,服务器扩容了,而且对传统项目而言,整体流程都是可控的,这是它的优点。
它的缺点不言而喻,有以下几点:
首先,它时效性太差,如果按照新浪服务器的采购周期,从审计到上线需要两个月的流程。两个月后服务器上线,恐怕刚结婚的明星都已经离婚了,突发事件流量都已经过去了。
另外,它无法准确预估容量,在传统的业务运维模式下,范冰冰分手、双宋离婚带来的流量是无法实现的,我们无法评估扩容量。
除此之外,传统模式下资源利用率比较低,服务器很难在业务间共享。
在这些问题共同作用下催生了动态扩缩容体系。
弹性计算:实时动态扩缩容
动态扩缩容不是一个工具,是一整套体系。它基于云服务,包含了在线压力检测和消耗度评测的功能,最终实现分级治理。
①弹性计算架构
首先简单介绍一下弹性计算的架构,弹性计算依托于 Kunkka 自动化运维平台,以及 Oops 监控平台,在业务压测的情况下获取业务指标监控,将数据送到容量决策系统,做出是否扩缩容的决定。
在云服务商方面,我们常用阿里云、华为云跟一部分自建的私有云。DCP 混合平台是我们微博另外一个团队做了几年的平台,它能够对接云服务,快速生成云主机快速扩容。
今天的重点跟业务方有着最直接的关系:业务上要不要扩容?什么时候扩容?扩多少?我们要解决这样的问题。
②决策系统
在上文的架构中,我们提到了容量决策系统,容量决策系统实际上指的是计算系统,会对我们获取到的业务指标进行计算、评估。
比如系统的基础信息、一些业务上日志来源的信息等,得到当前业务的容量,通过对历史数据进行同比、环比的分析,得到流量趋势,了解接下来流量会变成什么样子,这两组数据计算结果会给出扩缩容的建议。
同时,他们会计算这些数据并予以呈现,提供一个辅助的 API 接口,给上下游部门做扩缩容数据。
③容量评估方法
这个业务的当前容量是什么样的?是不是健康的?这个指标靠什么来评估?
由于业务系统、业务形态、架构的不同,选取一个实时且通用的指标是非常具有挑战性的,我们也尝试了很久,引入了 AVG-hits 的概念。
对于处在不同时间内的请求数进行加权、求和来拟合实际的单机消耗量,这个代表的是在不同的区间的耗时数,我们给它一个系数,大于 5 毫秒小于 10 毫秒,根据自己的业务给予耗时分区,这样就能计算出来。
事实证明,与之前传统的单一 QPS 负载对比起来,综合的数据对业务的评估比这种单一指标是更加准确的。
在获得这个数据之后是不是就能够描述当前的系统容量呢?
回答是肯定不能,AVG-hits 这个概念第一次接触,确实是有点生涩,举个简单的例子来帮助理解,比如说某个业务消耗指标衡量非常简单,需要通过内存判断消耗情况。
如果监控指标提示内存消耗到 80G,那能不能用 80G 来描述当前系统的消耗情况?
这样问就比较容易理解,回答肯定是不能的,因为不知道服务器最大的内存是多少,如果最大是 96G,那么 80G 已经超过 80% 了,接近危险值,如果最大内存是 256G 则消耗不到 30%,是非常安全的值。
道理是一样的,仅拿到当前消耗值是不能对业务当前状态进行描述的,还需要另一个评估标准。
这个业务当前能承载的最大容量是多少?如果是看内存就简单了,可这是一个综合评估标准,要怎么拿到它呢?
作为一个有经验的运维,我觉得根据服务器当前硬件的表现,猜测最大容量不是困难的事情,但现在都 2019 年了,靠猜是不行的,我们通过压测获取最大容量值。
在实际环境中减少服务器数量,减少到不能再少,记录当前的容量值,作为最大容量,用压测开始之前的实际消耗值除以压测获取的最大容量,得到整个系统的消耗比。这个消耗比就认为是当前这个系统消耗的画像。
压测压到什么情况下达到最大容量不能再压呢?是要压到服务器宕机?
我们接入了另外一个概念叫消耗比,在耗时最大区间的 Ahits(请求数量)数(PPT 上显示:慢速比=100.0*当前容量(Ahits)/最大容量(max_Ahts))与总的请求数之比超过一定的比例,则是影响用户的体现。
这个压力达到最大值就不能再压了,就会记录当时的 Ahit 数,作为这个接口最大容量。
④分级治理:水位线
现在拿到了一个非常重要的容量值及消耗比来进行容量评估,用于描述当前的容量消耗情况。
拿到这个消耗比之后是不是就可以扩容了?还是可以缩容了?此处还需要一个评估标准,是 30% 就扩?还是 50% 再扩?
我们基于历史数据给予分析,制定了三条水位线,包括安全线、警戒线和致命线,拿当前消耗值与水位线进行对比,在不同阶段采取不同的措施。
比如,现在的消耗度远远低于安全线,说明现在服务器部署有冗余,我们可以进行逐步的缩容。
如果说现在已经高于致命线,则需要扩容,让这个值更加接近安全线,保证系统的稳定性。
⑤在线容量评估体系
现在自动扩缩容的三个要素,当前消耗、水位线、容量决策系统都已经具备了,我们如何把这三个点联动起来?如何让它串在一起完成扩容动作?这些环节都包含在在线容量评估体系内,这个体系可以实现压测的过程。
我们刚才说了压测不是通过流量拷贝进行模拟测试的,我们是针对目标服务,就用线上的流量,记录当前(Ahits)数,开始减少服务器的数量,一直到慢速比达到临界值的时候,记录 Ahits 数作为本服务单元最大的消耗。
得到消耗值后和水位线进行对比,调用决策系统做出是否扩缩容的决定,接下来再对接云服务商,就完成了扩容的动作。
⑥实时演练体系
前面进行的数据采集、计算,以及动作的串联,都是为了完成最后一个目标,服务扩容成功。
真正的服务器扩容到线上之后,怎么样才能保证服务是健康可用的呢?我们还有另外一套辅助系统叫扩容演练。在实时演练过程中,要注意以下几点:
部署效率:我们通过扩容演练来寻找整个扩容过程中的瓶颈,比如,我们下发是通过 DCP 对接云服务商来完成扩容的。
在真正的线上扩容过程中,DCP 有时要同时承载几千台节点的扩容并发。DCP 的效率是否能够满足?在扩容演练过程中需要确认这一点。
带宽限制:微博和云服务商之间确实是拉了专线,但是微博和云服务商不只是微博广告的一个业务,还有很多其他大户。
而且一般在流量增加的时候他们的扩容也是非常猛烈的,所以带宽是否可用,也是我们在日常演练过程中非常注意的现象。
依赖服务:这方面有很多案例,在这里简单分享一下,2015 年春节,自动扩缩容的流程才刚刚开始,春节当天晚上我们扩容完几千个节点后,忽然发现负载均衡加不上去。
之前做过演练,但不会拿几千台云服务器进行扩容,可能几十台确保功能可用就可以了,到时候要让负载均衡的同事通过配置文件增加下 Memeber 就可以。
如果上千台的服务器没有办法增加到负载均衡设备,那个时候大家手忙脚乱,最后通过手动的方式扩容节点。
大家知道春晚的流量高峰很短,但那天确实给了我们当头一棒。接下来我们在扩容演练过程中,不仅会对负载均衡进行确认,还会对我们依赖的服务进行确认。
比如每次发生热点事件时,大家会说微博又崩了,评论又崩了,热搜出不来了。
其实应对峰值流量是件很头大的事情,我把事情解决了,兄弟部门没有解决,兄弟部门解决了,姐妹部门又出现了问题。
安全限制:618 大促时,京东的同学分享了在扩容的时候新增的服务器 IP 与 VIP 发生了冲突,而微博主要的体现就是数据库会对很多业务的请求设置白名单,可是云服务器扩容之后 IP 是随机的。
另外,新浪对于通行证有很多 IP 限制,所以我们通过扩容演练体系不断发现各个环节中的问题,加以解决,保证在扩容动作进行时能够顺利地完成,保证扩容出来的云主机真正安全上线服务。
有了这个系统的加持,截止到现在自动扩容服务都处于比较稳定的状态。
智能监控
在上文提到的自动扩缩容体系当中,提到一个叫 Oops 的系统,这是微博广告运维人员建立的智能监控系统,接下来给大家简单介绍一下。
监控面临的挑战
说到监控,不得不说监控遇到的很多问题。市面上有很多开源的监控软件,比如说常见的 Zabbix,在监控数据量少的情况下,不管是基础监控还是业务监控,这些开源软件都是可以直接满足需求的。
但是随着监控指标的增多,加上我们的指标是实时性变化的,数据要求又比较高,这些原生软件不再满足我们需求了。
另外,微博广告的业务数据有特殊性,一般运维关注的数据是系统的性能,系统的性能数据有时候来源于业务日志。
但是微博广告的业务日志是收入,很多业务日志是一条都不能丢的,比如说结算的曝光。
每一条曝光对于广告来说,都是真金白银,对精准性要求比较高,单独通过性能监控的日志收集方法是不能满足需求的,这也是我们面临的挑战。
另外,监控系统一般都会具备告警功能,有告警就会有告警问题,接下来会详细地介绍告警问题。
还面临定位方面的挑战,在监控越来越完善的基础上,很多开发的操作情况发生了变化。
一旦发生问题,第一个反应并不是上服务器看一下系统怎么了,而是翻监控,看看哪些监控指标发生了问题,所以监控系统会越来越多地面向于问题定位这个方向。
Oops 整体架构面临的挑战
作为监控系统,Oops 在架构上并没有什么出奇的地方,所有的监控无非就是四个阶段:
- 从客户端进行数据采集
- 数据的清洗和计算
- 数据存储
- 数据展示
监控数据流向特点
所有的监控系统都逃不开这四个阶段,只是根据业务的不同进行了定制化的工作。
针对广告业务的监控流向,我们把数据分成两类,有一部分精密数据的计算,我们采取的是离线分析的方式,通过采集软件将所有的日志采集到 Kafka,通过计算的工具进行拆洗、计算,计算之后落存储。
还有另外一个团队开发的针对于这一部分数据的页面展示化,还有一个系统叫 Hubble,针对精细数据的展现,实现个性化定制的展现。
另外一部分是运维比较关心的数据,今天来了多少流量?流量有多少是正常的?有多少是异常的?平均耗时是多少?针对这一部分,我们采取了实时数据计算的方法。
在数据采集阶段发生了变化,我们并不采集全量日志,而是在客户端做了预处理,进行分类计算。
比如说监控数据,就按监控数据的方法计算;告警数据,就按告警数据的计算。而且按照用户读取的需求进行分类存储,保证了高并发数据的实时性。
海量指标监控系统流程
接下来详细介绍实时数据计算。
首先从数据采集上讲,上文提到我们不采取全量的采集方式,而是通过 Agent 对数据进行处理。
在数据采集阶段,在数据产生的服务器上,针对不同的需求按不同的时间进行分类聚合,最终向后推送的数据是 key-value、计算方法这种模式,推送给 Proxy。
Proxy 拿到已经被打包的数据进行拆包,然后送给不同的计算结点,再按照 Key 进行计算,打时间戳。
这个数据并不精准,但我们可以接受部分损失,只需要保证数据的趋势是正确的。
另外,关于分类计算,不同的需求推送给不同的计算节点。存储也进行了分类,实时性要求比较强的话会直接放到内存,以最精细粒度进行存储。
前三个小时的数据是按秒存的,按天计算的数据是按 10 秒、30 秒存的,一些单机数据是按分钟存的。
另外一些历史性的数据需要出报表的,比如说要看前一周的数据,前一个月的数据,按照大数据的方式存到 OpenTSDB 当中。
存储的数据提供一个 API,通过 API 我们进行了分类计算、分类存储,这种分类的需求来源于用户,需要看用户有什么要求,要什么样的数据。
比如,Dashboard 的展示数据会直接被放到内存里。另外,上文提到的在线扩缩容数据,会相应获取数据给用户,其他相关的获取需求 API 也会进行分类获取。
接下来我们计算过的数据还有一部分会存储到 Redis 通过 WatchD 作为告警中心的数据,因为告警数据一般都只要求当前数据,不会有人需要查看上个月这台机器的负载有没有告警。
所以 Alert 节点计算之后的数据直接存在 Redis,Redis 把这个数据拿出来之后经过告警中心根据告警规则进行清洗,通过各种方式推送到需求方。
同时有一个相对个性化的展示叫九宫格。我们的九宫格实际上是一个结合报警功能的监控,它是一个页面,但具备了告警功能。
接下来看一下监控图,下面三张图是范冰冰宣布分手拿到的流量,我们的反映是非常灵敏的,平均耗时也涨上来了。
第三张图是拿到这些数据之后,自动平台显示应该扩容了。蓝色跟绿色的流量线已经降下来了,大部分量调到云服务器上。
下图是我们的九宫格,因为时效性比较强,正常来说是以产品为页面,以业务线为格子,每个格子记录的是单机的详细信息。
如果在这一组服务器当中单机故障数超过一定的比例,这个格子会变颜色。
所以在正常的运维工位上都会有这样的大屏幕,运维可以一目了然发现自己所有负责的业务线情况,而不是让一台台机器在这里展现,这样就没有办法看到业务线情况了。九宫格可以让运维更加直观地看到当前的告警情况。
告警
告警有很多的问题,我们遇到的问题可以分为以下四个方面:
①告警数量巨大
运维人员需要关注所有部分,从系统到服务、接口等等,维度很多,一旦有问题,各种策略都会触发报警,报警数量多到一定程度,基本上等于没有报警。
②重复告警率高
告警策略一般会周期性执行,一直到告警条件不被满足,如果服务一直不恢复,就会重复报下去,另外,同一个故障也可能引发不同层次的告警。
比如,我们有一个业务线叫超粉,会有 360 台服务器,流量高峰时 360 台服务器会同时发送告警,这种告警的重复率很高。
③告警有效性不足
很多时候,网络抖动、拥堵、负载暂时过高或者变更等原因,会触发报警,但这类报警要么不再重现,要么可以自愈。
比如一个硬盘在接近 80% 的时候开始告警了,你让它告吗?好像得告,但似乎不告也可以。
④告警模式粗放
无论是否重要、优先级如何,告警都通过邮件、短信、App PUSH 发送到接收人,就像暴风一样袭击着接收人,接收人没有办法从中获取到有效的信息,经常会让真正重要的告警淹没在一大堆普通告警中。
针对这些问题,我们采取了以下措施:
①抖动收敛
对于这种大规模服务器的维护,抖动是非常常见的现象。网络抖一抖,整个服务单元就会向你告警。
针对这种抖动,我们增加了一些策略,抖动的时候会前后比较,监测重复性,看看是不是具备告警的意义,通过增加告警策略这种方式来进行收敛。
比如说流量突增的时候,需要查看是不是同单元都出现了这个情况。
②告警的分类和分级
详细定义告警级别,发送优先级、升级策略等,可有效减少粗放模式下告警接收量。比如,一些低优先等级的告警会让它告,处理的级别会低一点。
③同类合并
同一个原因可能会触发一个服务池里面的所有实例都报警,比如同时无法连接数据库,其实只需要报一次即可。
④变更忽略
我们的好多变更都是在 Kunkka 平台上操作的,开发有时候会选中一个通知,现在是变更,告警请忽略。
以上措施能解决告警问题中 80% 的问题,现在大家都在朝着更高级的方向发展,我们也简单做了一些探索。
在原有告警数据流情况下引入了工具 SkyLine,这个工具包含了多种算法,在异常检测环节中,能够通过它内置的算法将我们传入的数据自动去抖动,提供平滑的数据,等你再拿到这个数据时就不需要再检测是不是告警。
这个工具避免了人工操作,通过 Skyline 将数据进行平滑,提供一份准确的数据,我们只需要通过这份数据,进行规则判断,决定是否需要告警就好了,减少了对数据准确性判断的复杂过程。
接着是根因分析部分,随着监控的覆盖面越来越广,监控精确性越来越高。
等故障出现的时候,开发人员就会去翻监控图,去查看大概是哪些原因导致了故障。
随着 Dashboard 越来越多,即便是经验非常丰富的工作人员也很难快速地定位到原因会出现哪个方面、该去看哪张监控图。
出现流量突增的情况时,Skyline 会通过内部的算法 Luminosity 寻找相似的情况,查看相同的时间内是否有其他地方出现流量异常,并将根源问题展示在 TOPN 上。
这样就能够快速查看在故障出现的前后哪些业务也出现了流量变化,方便对故障原因进行分析和定位。
服务治理
还有一项非常重要的工作——服务治理,这里只进行简单的介绍。
为什么需要服务治理
微博广告现阶段所出现的问题主要有:架构越来越复杂,上文提到微博广告的服务器已经达到 3000 台。
所以在这种服务器数量情况下,架构会越来越复杂,稳定性要求也变得非常高;开发的多语言环境对上线发布也造成了挑战;资源使用是否合理,对运维来说也是一个挑战。
低成本和高可用的平衡
针对这些问题,我们进行了低成本和高可用的平衡,争取用最小的服务器达到最稳定的架构。
在保证服务稳定的情况下,将流量进行均分,分到最小服务单元三机房部署为基本规则,保障在一个机房挂掉的情况下,另外 2/3 的服务器能承载全部的流量。
关于上下游之间调用的平衡,尽量减少跨运营商的调用,微博广告每一毫秒的消耗都会影响到收入。
我们的请求时间是 1 毫秒、1 毫秒地优化下来的,这些损耗产生在网络和服务器上,很难通过人力弥补,因此在这方面我们也非常谨慎。
另外,小功能会抽象出功能的共同点,将这些功能服务化,服务则按单元化部署。
服务发现及负载均衡
在服务治理过程中,我们会根据服务的引入服务自动发现,尽量减少服务变更环节的人工干预,提高安全性和实时性,自建负载均衡会有标准的数据输入和数据发布的过程,可以大大提升后期的可扩展性和可用性。
服务治理成绩
经过近半年的服务治理,我们达到了这样的成绩:
- 架构更加强健,容灾能力提高
- 系统、数据、配置标准化
- 服务器的合理使用,成本控制
其中,我觉得最重要的是系统、数据、配置标准化的过程。
今天好多分享的嘉宾也提到了 AIOps,这些上层的建设都是依赖于整个业务标准化的过程。
中国有句古话,工欲善其事,必先利其器,我们所有的标准化过程就是为下一步人工智能打下坚实的基础,希望我们的工作能够以技术保证微博系统稳定,助力微博广告的收入。
孙燕,微博广告基础运维负责人,2009 年入职新浪,任职 10 年间参与博客、图片、视频、微博平台监控、微博广告多个产品运维,致力于运维自动化、产品架构优化、服务治理、智能监控及以监控为依托的服务容灾建设。