百度多维度数据监控采集和聚合计算的运维实践分享

运维 系统运维
我是百度运维部平台研发工程师颜志杰,毕业后一直在百度做运维平台开发,先后折腾过任务调度(CT)、名字服务(BNS)、监控(采集&计算);今天很高兴和大家一起分享下自己做“监控”过程中的一些感想和教训。

大家好,我是百度运维部平台研发工程师颜志杰,毕业后一直在百度做运维平台开发,先后折腾过任务调度(CT)、名字服务(BNS)、监控(采集&计算);今天很高兴和大家一起分享下自己做“监控”过程中的一些感想和教训。

  现在开始本次分享,本次分享的主题是《多维度数据监控采集&计算》,提纲如下,分为3个部分:

  1.监控目标和挑战

  2.多维度数据监控

  2.1.采集的设计和挑战

  2.2.聚合计算的设计和挑战

  2.3.高可用性保障设计

  3.总结&展望

  首先进入***部分 :监控目标和挑战,先抛出问题,装装门面,拔高下分享的档次(个人理解,欢迎challenge)。

  监控期望做到:快速发现问题,定位问题(运维层面),解决问题,甚至要先于问题发生之前,预测/防患未然,形成处理闭环,减少人工决策干预。

  先解释一下“定位问题(优先运维层面)”,意思是站在运维角度“定义故障”,不需要定位到代码级别的异常,只需定位到哪种运维操作可以恢复故障即可,比如确定是变更引起的,则上线回滚,机房故障则切换流量等…

  不是说监控不要定位到代码级别的问题,事情有轻重缓急,止损是***位,达到这个目标后,我们可以再往深去做。

  再解释下“预测/防患未然”,很多人***反应是大数据挖掘,其实有不少点可以做,比如将变更分级发布和监控联动起来,分级发布后,关键指标按照“分级”的维度来展示。(记住“分级”维度,先卖个关子:)

  “监控目标”这个话题太大,挑战多多。收敛一下,谈一下我们在做监控时,遇到的一些问题,挑两个大头,相信其他在大公司做监控的同学也有同感:

  1.监控指标多,报警多

  2.报警多而且有关联,如何从很多异常中找出“根因”

  今天先抛出来两个头疼的问题,下面开始进入正题“多维度数据监控”,大家可以带着这两个问题听,看方案是否可以“缓解”这两个问题。

  进入正题:

  先看***个问题:监控数据多。监控数据符合28定律,“关键”和“次要”指标需要区别对待,不能以处理了多大数据量引以为傲,需要按重要性分级处理,将资源倾斜到重要数据上分析和处理。

#p#

  监控一个服务,把精力放在那20%的关键指标数据上,80%的次要指标作为出问题后,分析根因所用,如何采集关键指标,留到采集一章,下面以百度某产品线接入服务为例来说明“关键”指标处理有怎样的需求。

  下面以百度地图产品线接入日志为例 (典型的nginx日志):

  1. 223.104.13.177 - - [27/Jul/2015:16:08:21+0800] "GET /static/apisdk HTTP/1.1" 200 36224 "-""-" "Dalvik/1.6.0 (Android 4.4.2; HUAWEI MT7)" 0.0020501076098 223.104.13.177 10.202.19.40 10.202.68.25:8210 www.baidu.com 

  百度地图接入服务需要有这些监控:按照运营商、省份、省份&运营商pv/平响;不同urihttp_code在不同机房pv/平响, 请求手机操作系统版本的pv…

  可以看到,一个指标会变为多个指标,比如pv监控项按照 5大运营商*36个省份 * 5个机房将产生900个指标数据,人工管理这种配置很困难,而且如果新增机房,需要新增配置5*36=180个配置,这个就不是人干的了。

  同时,这些指标之间是相互关联的,自然想知道地图pv数据,在哪几个运营商,省份,机房有数据,所以需要对监控项进行meta管理。

  总结一下,“关键”指标数据需要多角度/多维度观察,会一点变多点,这些多点数据有关联,需要meta管理,简单配置,那么如何来解决呢?

  数据模型先行*3(重要的事情说三遍),选择一个好的数据模型来组织监控数据,解决上面提到的问题,将会有不同的效果,下面是两种数据模型的优劣(也是我们自己的监控历程)。

  贴一下图:

  监控数据需要多角度观察,这是强需求,在一维数据模型中,将维度信息放在了监控项名字里面,比如nginx_pv_city_beijing_isp_unicom表示的是北京联通的pv,nginx_pv_city_beijing_isp_cmnet表示北京中国移动的pv。

  这种数据模型,监控项间无关联,除非对名字做一系列规定,并增加对名字做split操作之类,否则很难让上面两个数据产生关联;而且配置的个数是维度的笛卡尔积。

  参考aws的cloudwatch,有了多维度数据模型,通过tags来扩展维度,比如把运营商、省份放到tags字段里面,这样用一份配置产生900关联的监控数据;并加入了product字段,在数据分级,权限控制上有作用,后面再展开。

  日志里面没有运营商和省份,机房信息,是如何获得的呢?这些我们统一叫做“运维元信息”,先卖个关子,待会在采集那一节展开,不过大家可以先有个印象,tags里面“维度”的取值可以做到很有“扩展性”。

  所以结论是,监控数据符合28定律,重要数据需要多角度观察,会产生多个相关联数据,需要有meta管理,需要动态简单配置。多维度数据模型可以很好的解决这些问题,内部我们将处理这数据模型的监控叫“多维度数据监控”。

  多维度数据监控在处理/资源消耗上没有减少,900个数据一个不少,所以我们将这套解决方案定位在处理“关键”数据,倾斜资源;而且只关注不同维度的聚合数据,单机数据在单机上存储即可,这都是基于资源的考虑。

  铺垫了这么长,现在看看“多维度数据监控”的框架拆解:

  典型的分层处理架构,采集=>计算=>存储=>报警+展示,没什么特别说的,想要强调2点:

  1.数据模型先行,任何的一个层级只要符合“多维度数据模型”都可以独立使用,每个层级都是服务化的。再强调一下“数据模型先行”。

  2.聚合流式计算分布式架构,不暴露开源实现,开源之上都有适配层,很多的处理可以在适配层展开,这个好处在可用性章节具体展开。

  下面开始依次介绍多维度采集&聚合计算&高可用性保证三个小节:

  先介绍采集,如果大家对logstash熟悉那***,采集agent很多功能点都是借鉴logstash来写的,当然设计上有些改动,欢迎拍砖。

  数据采集就是一个标准化的过程,服务以某种方式吐出数据,采集负责把数据转换为监控数据模型,发往下游处理;所以理想情况是推监控标准,服务链接监控lib,lib将服务核心指标吐过来。

  理想我们在努力中,然而… 所以,目前,关键指标大部分通过日志来获取,遇到的挑战是:

  1.日志量大=>不传原始日志,而且在agent做各种手段来减少数据传输。

  2.日志如何规整化=>参考logstash,用命名正则来规整。

  3.tags要做到很有‘扩展性’=> agent端需要支持对tag的自定义。

  依次来说,***如何降低数据传输,首先单机会做聚合,即一个周期内(如10s),所有tags取值相同的监控会合成一条数据发送。比如百度地图接入服务中,10s内来自北京联通的请求变成一条监控数据,这个策略实践证明对于减少数据是很明显的。

  数据减少手段还有ETL和公式计算,agent端就确定哪些数据是不用传递的,比如实现dict映射,只有在字典dict内的值才放行,其他的都归结到other里面。

  比如,运营商其实有20+,但一般OP就关注4大运营商,所以可以通过dict将其他的运营商都归结到“other”里面,而且还支持重命名,既规整了tag的取值,又减少了数据的传递,比如有如下的dict:

 

  1. "dict": [  
  2. "CHINANET => 电信" 
  3. "UNICOM => 联通" 
  4. "CMNET => 移动" 
  5. "CRTC => 铁通"  

  #p#

公式计算也如此,尽早的过滤不需要的数据,我们支持四则,逻辑运算,当agent端具备这样的表达能力后,扩大了agent采集的能力,可以采集很多有意思的监控项:

  比如根据nginx的响应时间${cost}和http错误码${errno},去定义损失pv,通过公式:${cost} > 2000 || ${errno} != 200 时间大于2s或errno不等于200,保证聚合计算功能纯碎性,降低数据传输量。

  第二个问题,日志如何规整化,通过命名正则来格式化文本日志,我们用c++写的客户端性能较logstash快不少,这里强调一下,我们没有像logstash一样可以支持多个线程去做正则,只有一个线程来计算,这样做的考虑是:

  正则匹配成功性能还可以,一般性能耗在不匹配的日志,出现不匹配的时候,正则会进行一些回溯算法之类的耗时操作,agent设计尽量少进入处理“不匹配日志”。

  通过增加“前置匹配”功能,类似大家去grep日志的时候,“grep时间戳|grep–P ‘正则’ ”,字符串查找和正则匹配性能相差极大,agent端借鉴这个思想,通过指定字符串查找过滤,保证后面的日志基本都匹配成功,尽量避免进入“正则回溯”等耗时操作,在正确的地方解决问题。

  这种设计保证agent最多占一个cpu。实践证明,通过“前置匹配”,保证进入正则日志基本匹配成功,几千qps毫无压力,而且一般只占一个cpu核30%下。

  第三个问题,Tag扩展性,tag是整个多维度监控的精髓,首先我们支持用户自定义任何tag属性,有统一的接口提供,你可以对监控数据上定义任何的tag,比如搜索服务里面可以加上库层属性。

  前面提到的运营商、省份,这个通过在agent端用一个ip库来实现反解,当然ip库更新是一个问题,目前随着agent的升级来进行更新,时效性不高。大家可以考下为何不放在server端处理:)

  日志采集agent通过上面的一些手段,基本满足了在关键指标的采集上的要求,完成了“标准化”,数据“精简化”的需求。

  总结一下,日志采集就是标准化的过程,通过采集配置将日志里面的信息变成多维度的数据模型,发送给后端模块处理。

  跟logstash比,想强调前置匹配功能点,没有借鉴其多线程处理的设计,坚持单线程处理,如果监控需要消耗太多的资源去达到,那么我就对这个合理性存疑了。

  采集就介绍到这,下面开始介绍实时汇聚计算。

  前面提到,多维度数据监控不关注“单机”数据,只关注聚合数据,那首先***个问题,怎么圈定“聚合"范围?这块功能在名字服务中实现,名字服务不展开。

 

[[153583]]

  如上图,通过名字服务完成聚合范围的圈定,支持三级范围圈定(实例id=>服务=>服务组),一个机器上的模块称为实例,实例发送的数据就是刚刚上面讲的采集agent发出来的,每个数据都带一个id标示,称为实例id。

  范围圈定后,通过指定聚合规则,我们拼成一个聚合所需要的数据结构,这个数据是自包含的,即监控数据+聚合规则都包括在里面,如下图所示:

  将多维度数据+聚合配置变成聚合自包含数据,自包含数据包含了怎么对这个数据进行计算,上面标示要按照isp运营商汇聚,以及按照运营商和城市来汇聚。

  有了聚合自包含数据后,就开始进行汇聚计算,如下图所示:

  首先我们只支持一些特定的运维算子,计算count、sum、avg、分位值、min/max基本上能涵盖运维的需求,比如count就是pv,sum/avg/分位值算平响等。

  遇到的挑战包括:

  1.单个汇聚的数据量过大,比如要计算10w机器的cpu_idle,最终需要要按照filed去累加,过大数据缓存累加,容易OOM,这个需要考虑storm的算子设计。

  2.数据范围的圈定是支持三层,也就是数据上卷操作如何来支持。

  先来看***个问题,介绍storm算子的设计,大家看下图:

  整个topology做到了无状态,处理的数据是自包含,其次计算加了一层预处理bolt,先用shuffer来处理一层,降低field到聚合bolt的计算量。比如计算10w机器的10s 钟cpu_idle(1wqps)先用10个预处理bolt,每个bolt就是只要累加1/10的数据,然后到下一层的计算量就会较小了。

#p#

  算子可以这么设计是因为计算avg不受影响,avg=sum/count,把10s sum加起来,和先加2s的sum,然后2s中间结果再加起来,除以count,精度没有损失,但分位值有精度损失,这个需要权衡。

  storm算子设计就介绍到这,下面开始介绍数据上卷操作。

  数据上卷在接入层做数据一维打平,在接入层的时候按照名字服务的圈定范围变成了多份自包含数据,比如实例1=>服务2=>服务组3,那么来自实例1的数据就变成两条数据。

  这两条数据一个范围属于服务2,一个属于范围服务组3,其他都一样,也就是牺牲了计算资源,保证整个计算数据都是不相关的,这个其实是有优化空间的,大家可以自己考虑。

  到这里多维度采集&计算基本功能点介绍完了。下面就介绍下稳定性的考虑了。

  此处有图:

  前面一直强调数据符合28定律,所以这个系统首先要支持流控,支持按数据重要性做优先级处理,有如下措施:

  ***,接入adaptor层,实现按产品线作为流控基本单元,和使用统计,谁用的多就必须多出银子,通过设置黑白名单,当出现紧急情况下,降级处理。

  第二,聚合计算做成整个无状态,可水平扩展,多机房互备,因为kafka+storm不敢说是专家,所以在应用架构上做了些文章,主要为:

  数据按照名字服务的范围圈出来后,我们发现,只要保证圈出来的“同一范围”的数据保证在同一个计算单元计算,就没有任何问题。

  比如建立两个机房集群1,2,每个机房建立3个kafka topic/ storm计算单元,取名为A,B,C计算单元,通过adaptor,将接收的数据做映射,可以有如下映射:

 

  比如地图产品线的接入服务,命名为:map.nginx,只要范围map.nginx的数据映射到一个计算单元即可,可以用如下规则:map.nginx接入 => 集群2,1计算单元A

  这样所有map的接入nginx数据就直接将数据写入到集群2机房的A计算单元来完成,集群2的计算单元B挂了,当然不会影响map.nginx。

  总结来说,整个计算都是无状态,可水平扩展;支持流控,当有异常时,可以进行双机房切换,如果有资源100%冗余,如果没有,就选择block一些产品线,服务降级。

  到这里,整个多维度监控采集和计算介绍完成了:)下面说一下总结和展望吧!

  采集就是一个标准化的过程,文本用命名正则其实是无奈之举,期望是pb日志,这样不会因为日志变动导致正则失效,而且性能也会提升;APM也是一样,这个类似于lib的功能,不用通过日志能采到核心数据。

  个人很看好pb日志,如果能够有一个通用的pb模板,有一个pb日志的规范推得好,那么还是很有市场的,以后只要这么打日志,用这个模板的解析,就能得到很多内部的数据,不用写正则。

  采集就是一个标准之争的权衡,估计你不会骂linus大神为啥把进程监控信息用文本放在/proc/pid/stat,而且进程名为啥只有16个字节;标准就在那,自己需要写agent去将这个标准转换为你内部的标准。

  当你自己推出了监控标准,在公司内部用的很多的时候,RD/op需要努力的去适配你了,他们需要变换数据格式到监控标准上;所以,到底是谁多走一步,这个就需要看大家做监控的能力了:)

  聚合计算的考虑则是各种算子的丰富,比如uv,还有就是二次计算,就是在storm计算的数据之上,再做一次计算;比如服务=>服务组的上卷操作可以通过二次计算来完成。

  比如服务组包含了服务1、服务2,那么我们可以先只计算服务1、服务2的pv数据,然后通过二次计算,算出整个服务组的pv数据 ,由于二次计算没有大数据压力,可以做的支持更多的算子,灵活性,这个就不展开了。

  我总结一下:

  1.28定律,监控需要倾斜资源处理“关键”指标数据。

2.关键指标数据需要多维度观察,1点变多点,这些数据是相互关联,需要进行meta和配置管理。

3.系统设计时,数据模型先行,功能化、服务化、层次化、无状态化。

4.对开源系统的态度,需要做适配,尽可能屏蔽开源细节,除了啃源码之外,在整个应用架构上做文章,保证高可用性。

  答疑环节

  1.抓取数据的时候需要客户端装agent?必须要agent吗?

  从两方面回答这个问题吧!首先系统设计的是层级化的,你可以不用agent,直接推送到我们的计算接入层;其次,如果你的数据需要采集,那么就是一个标准化的适配过程,比如你的监控数据以http端口暴露出来,那么也需要另一个人去这个http端口来取,手段不重要,重要的是你们两个数据的转换过程,所以不要纠结有没有agent,这个事情谁做都需要做。

  2.采集之后,日志是怎么处理的?

  日志采集后,通过命名正则进行格式化,变成k:v对,然后将这些k:v对作为类似参数,直接填写到多维度数据模型里面,然后发给聚合计算模块处理。相当于对日志里面相同的字段进行统计,上面说的比如地图nginx日志的处理就是这样。

  3.elesticsearch+logstash百度有木有在用呢?还有kafka在百度运维平台中的使用是什么状态呢?

  ELK在小产品线有使用,这个多维度监控可以大部分的情况下替换ELK,而且说的自信点,我们重写的agent性能快logstash十倍,而且符合我们的配置下发体系,整个运维元数据定义等;kafka在刚刚的系统里面就是和storm配合作为聚合计算的实现架构。

  但我想强调的是,尽量屏蔽开源细节,在kafka+storm上面我们踩过不少坑。通过上面介绍的这种应用框架,可以保证很高的可靠性。

  4.多维度数据监控在哪些场景会用的到,可以详细说下几个案例吗?

  我今天讲的是多维度数据监控的采集和计算,没有去讲这个应用,但可以透露一下,我们现在的智能监控体系都是在刚刚讲的这一套采集&计算架构之上;每层都各司其职,计算完成后,交给展示/分析一个好的数据模型,至于在这个模型上,你可以做根因定位,做同环比监控,这个我就不展开了。

  5.能介绍百度监控相关的数量级吗?

  这个就不透露了,但大家也都知道BAT三家的机器规模了,而且在百度运维平台开发部门,我们的平台是针对百度所有产品线;所以,有志于做大规模数据分析处理的同学,你肯定不会失望(又是一个硬广:)

  6.不同产品线的聚合计算规则是怎么管理的。不同聚合规则就对应这不同的bolt甚至topology,怎么在storm开发中协调这个问题?

  看到一个比较好的问题,首先我们设计的时候,是通用聚合计算,就计算sum/count/avg/min/max分位值,常见的运维都可以涵盖;我们通过agent做了公式计算,表达能力也足够了,同时有二次计算。不一定非要在storm层解决。

  我提倡“正确的位置解决问题”,当然大家对这个正确位置理解不同。

  7.topology无状态这句话没太明白。storm topology的状态管理不是自身nimbus控制的吗?百度的应用架构在此做了哪些工作或者设计?

  我说的是写的storm算子是无状态的,整个数据都是自包含的,我们在应用架构上,就是控制发给stormtopology的数据;多机房互备等;我说的应用架构师在这个storm之上的架构。相当于我认为整个storm topology是我接入adaptor层的调度单元。

责任编辑:火凤凰 来源: StuQ
相关推荐

2017-04-28 17:44:45

百度

2015-08-17 09:39:33

智能运维百度监控

2014-07-25 17:12:39

数据库WOT2014MongoDB

2015-09-01 16:42:55

新闻客户端百度数据源码

2014-11-03 10:00:46

Memblaze闪存

2022-06-21 07:51:15

云原生应用链路

2011-06-10 15:18:41

百度收录

2015-08-26 14:33:48

技术周刊

2017-01-21 14:38:54

百度网络运维网络工程师

2013-04-12 13:30:47

2018-11-26 23:00:56

百度运维管理

2015-12-14 13:54:51

百度运维大数据

2018-11-15 11:52:36

百度云运维AIOps

2011-03-23 17:28:03

2010-08-30 10:48:10

百度框计算云计算

2024-01-09 07:48:07

推荐排序算法策略数据背景

2011-06-22 17:40:36

SEO百度知道

2009-08-21 10:33:52

2013-08-22 17:08:50

2015-08-05 22:34:33

运维技术
点赞
收藏

51CTO技术栈公众号