前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【鹅厂网事】大型互联网公司海量监控系统设计

【鹅厂网事】大型互联网公司海量监控系统设计

作者头像
鹅厂网事
发布2023-03-07 12:11:34
6120
发布2023-03-07 12:11:34
举报
文章被收录于专栏:鹅厂网事鹅厂网事

"鹅厂网事"由深圳市腾讯计算机系统有限公司技术工程事业群网络平台部运营,我们希望与业界各位志同道合的伙伴交流切磋最新的网络、服务器行业动态信息,同时分享腾讯在网络与服务器领域,规划、运营、研发、服务等层面的实战干货,期待与您的共同成长。

网络平台部以构建敏捷、弹性、低成本的业界领先海量互联网云计算服务平台,为支撑腾讯公司业务持续发展,为业务建立竞争优势、构建行业健康生态而持续贡献价值!

(一)背景

近些年来,随着互联网的迅猛发展,各大互联网公司的服务器数量不断膨胀,如今十万级别的服务器规模,已经不再罕见。再加上虚拟化技术的成熟,每台物理服务器可以虚拟出多台虚拟子机,虚拟子机也会当成物理服务器进行监控,因此监控的机器数将是一个更庞大的数字。海量运营,监控先行,设计一个能支撑百万级海量服务器监控的系统,提升每人运营机器数,将成为海量服务器运营的关键。

(二)需求

2.1基础性能数据采集

如同厨师做菜必须有食材一样,监控系统首先也需要拿到原材料——基础性能数据。服务器的基础性能数据包括如CPU使用率、CPU负载、内存、磁盘容量、网络IO、磁盘IO、ping探测状态等周期性上报数据,还包括在服务器上检测进程端口存活性、系统重启、硬盘只读等产生的原始告警数据。采集到的数据,汇聚到中央,进行数据的存储与告警分析,再通过多种维度的图形化界面展示,让运维人员可以对服务器的基本运行情况了如指掌。

2.2自定义监控项上报通道

基础性能数据可以覆盖常见的监控场景,但对于业务运维人员来说,经常需要进行一些自定义监控项的采集。一种是数值型数据,例如运维人员想监控某个进程的一个内部变量值,如用户在线数。作为公司统一的基础架构监控系统,显然无法直接支持这种自定义监控项的采集,但可以向业务开放自定义监控项的上报通道。业务侧可以在进程里调用上报通道的接口,把用户在线数上报到监控系统,这样监控系统就可以对用户在线数进行图形化展示以及告警检测。另一种是字符型数据,例如有时业务运维人员会写脚本进行一些异常监控,当出现异常时可以调用上报通道的接口直接上报告警。

监控系统的上报通道屏蔽上报细节、屏蔽与短信网关、自动语音系统等的交互细节,把简单的接口提供给业务人员实现上报。运维人员首先在监控系统为上报的数据申请一个唯一的ID,然后在进程或监控脚本中调用接口,使用这个ID来上报数据。这样,业务运维就可以在监控系统查看该ID的曲线图或字符型数据。同时,还可以为这个ID设置一些告警策略,当符合某个告警规则时发出告警通知。

2.3告警

假设我们需要对某个进程的存活性进行监控告警,如何实现呢?运维人员可以写一个脚本,定期扫描进程,一旦某个进程不存在,则调用短信接口进行通知。但这种刀耕火种的方式,存在很多问题:

1、一旦进程不存在,每个扫描周期都会产生告警短信,大量的短信降低了告警短信的价值,而且可能淹没其它重要告警。

2、如果需要临时停止监控,只能逐台机器停掉脚本;继续启用监控时,又需要逐台机器启动脚本。

3、有时需要过滤掉抖动类的告警,例如希望在进程持续一段时间不存在的情况下才告警,对进程停止但很快又自拉起成功的告警希望忽略。

……

如果服务器数量少,这种方式可能还扛得住,但对于海量服务器,是无法接受的。因此海量服务器的监控,需要有一个统一的告警平台,可以根据各种告警策略进行检测,对原始的告警进行屏蔽、去重、合并、收敛等处理后,最终只发出最有价值的根因告警。

2.4数据分析

作为海量服务器的监控系统,每天可以收到大量的基础运营数据,这些数据蕴含着巨大的商业价值,对这些数据深度挖掘,可作为一些决策的参考依据,如机型选型、资源匹配、故障预判、流量计费等,这对于降低成本、提升可靠性有着重要意义。

监控系统的基础运营数据,也会通过数据转发、API调用等方式开放给公司各个业务的运营团队,结合业务自身工具与运维体系,将能最大程度发挥数据价值。

(三)实现难点与解决方案

3.1

采集层

3.1.1 实现难点

采集层是整个监控系统的根基。为支持数据采集,并向业务开放上报通道,保持最大的灵活性,我们通过开发一个运行在服务器上的agent来实现。而海量的服务器带来的海量agent,使采集层面临如下挑战:

1.稳定与安全

agent运行于公司赖以生存的海量服务器之上,若因agent异常而导致大量业务服务器故障,将造成严重事故。因此稳定与安全永远是第一优先级

2.海量agent接入

对于百万级的agent,显然无法通过一台服务器来支撑所有agent的接入。一方面,我们希望能利用尽可能少的服务器完成海量agent的接入,另一方面,接入层需要可以支持平行扩展,即使支撑千万级agent,只需要扩容接入点即可,无须对整个架构做大的修改

3.海量agent管理

海量的agent显然不能依靠人工来进行管理。需要有一套完善的系统来实现海量agent的自动化管理

4.非扁平网络

理想的网络世界是扁平的,但现实中,经常会出现因为某些网络限制,或是安全上的考虑,或是业务的特殊需求等,导致网络不可能扁平。采集层需要适应各种特殊情况来支撑监控。

下面来看看如何应对这些挑战

3.1.2 agent设计

如何设计一个稳定安全的agent?Unix的一个哲学,便是一个程序只做一件事,保持简单。当程序保持简单,足够的内聚,便可将复杂度降至最低,易于维护,最大可能地避免BUG。基于这个原则,我们对agent基于功能进行拆分,把agent拆分成一组高内聚,低耦合的进程,包括:

1、主控进程:提供上报通道,负责数据上报,升级管理。

2、采集进程:负责性能数据采集与原始告警检测。

3、调度进程:负责对agent插件的调度。

进程之间通过共享内存解除耦合。主控进程生成一块共享内存,并提供共享内存操作接口,采集进程采集到数据后,只需要调用共享内存操作接口,把数据扔到共享内存即可,无须理解数据上报到服务端的细节。数据的上报完全交给主控进程来完成。通过共享内存操作接口,实际上也是向业务开放了数据上报通道。业务进程需要上报一个性能数据,或是上报一个告警,只需要调用共享内存操作接口即可。

有时候运维人员需要自己写脚本,实现一些自定义监控项的采集。但这会涉及到一个脚本部署的问题。如果这个脚本需要部署在大量服务器上,没有自动化运维工具支持的话,将是一个繁琐的过程。因此agent还实现了插件机制,运维人员的自定义监控项采集脚本可以作为agent的一个插件来实现,提供了良好的可扩展性。

3.1.3 agent接入

为实现大量agent的接入,服务端进程接入collector尽可能保持简单,只做数据转发,不负责数据处理。而agent只是周期性做数据上报,连接大多数时间是空闲的,因此这种场景非常适合使用epoll来实现。接入collector内部使用内存消息队列将数据接收和数据转发解耦,可达极高的吞吐量。单台接入collector可支撑10W agent的接入。

尽管接入collector性能极高,但对于百万级的agent,需要实现分布式接入。一般会按地域搭建接入点,每个地域的接入点负责收集该地域所有agent的数据,再转发到下一级模块。这种分而治之的思想,使得agent接入可以平行扩展,任何时需要扩容,搭建新的接入点即可。

因为接入collector只做数据转发,不做数据处理,使得collector支持级联。通过级联,可以适应非扁平化网络。假设某个网络区域出于安全性的考虑,只允许少量机器对外通讯,这种限制会导致大多数机器的agent无法连接collector。针对这种场景,可以在允许对外通讯的机器上搭建collector,让该网络区域所有agent都上报到这个collector,再利用collector的级联能力,把数据转发到普通网络区域的collector,达到数据上报穿透的目的。

3.1.4 agent管理

程序总是需要增加新功能,或是修复BUG,agent也一样不可避免需要发布新版本。而对于百万级的agent,显然不可能人工进行版本发布,必须有一套自动、高效、安全的方法来实现agent版本的管理。agent的版本管理需要具备如下功能:

1.版本记录

记录每个agent的版本,知道哪台服务器运行着哪个版本的agent,这是我们进行版本升级的决策基础

2.自动升级

需要进行升级的时候,只需要配置升级规则,就可以在短时间内无须人工介入地自动完成版本更新

3. 灰度部署

agent运行在至关重要的服务器上,每次发布都必须严格控制风险,因此必须具备灰度能力。升级时,支持先小范围对非重要服务器进行更新,稳定运行后再逐步更新到其它服务器

4. 版本回退

如灰度过程发现BUG,需要很方便地支持agent版本的回退

5. 安全性

为保证下发文件的完整性与安全性,升级进程和agent需要对版本文件进行严格的校验

3.2

存储层

agent上报的数据分两种,一种是数值型数据,如当前的CPU使用率、流量值等,这是一种时间序列的数据;另一种是字符型数据,即异常时上报的告警。字符型数据会经过告警平台的去重、合并等,最终存储下来的数据量并不大,直接使用关系数据库存储即可。而数值型的数据则会大得多。agent会周期性上报服务器的各种基础性能数据,再加上业务自定义监控项的采集,平均每个agent上报的指标个数可达50-100左右,上报频率在1分钟-5分钟之间,每秒需存储的指标个数在50W以上,百万级的agent每天可以产生的100G以上的数据。告警系统、各个业务系统会频繁访问agent最新上报的数据,进行大量的告警分析和统计,因此还需要提供高性能的查询能力。

传统关系数据库如MySQL很难支撑如此大量的数据的读写。因此,我们需要设计一个分布式的时间序列数据存储系统。在存储机上,使用共享内存+文件的方式来保存数据,共享内存提供热点数据的快速查询、更新能力,文件则提供数据的持久化。文件的存储上,基于时间序列数据的访问特点,合理设计索引,并将索引数据内存化,使得能以最少的随机读盘读写次数来得到数据。分布式设计上,设计了高效、分布均匀,易于扩容,具备容灾能力的路由规则,数据写入和查询时,根据路由规则命中到对应的存储机上。这样设计的分布式时间序列数据存储系统,达到了高可用、高性能,并具备良好的平行扩展能力的要求,得以支撑海量agent数据存储。

3.3

告警层

3.3.1 实现难点

告警平台作为整个监控系统最核心的部分,直接关系到监控的可靠性、稳定性。如何对海量告警进行去重、合并、相关性收敛,做到不误告警,不漏告警,还不能多告警,并具备高可用、易扩容、易扩展特点,是一个巨大的挑战。

在功能需求上,告警平台需要具备如下功能:

首先,告警平台需要支持各种各样不同类型的告警,例如针对服务器的Ping不可达告警、磁盘容量告警、流量告警、进程端口告警等,针对业务的自定义监控项的告警,还有针对网络的各种流量、质量告警等。告警平台需要进行这些告警检测,产生原始告警。

其次,海量的服务器每时每刻都有大量原始告警产生,显然不能每出来一条告警就发出一次通知。因此除了原始告警检测,告警平台至少还需要具备下面的功能:

1) 屏蔽:日常运营中不可避免需要对某些可预知的告警进行屏蔽。

2) 去重:当一个告警通知负责人后,在这个告警恢复之前,负责人不会希望继续收到相同的告警。

3) 抑制:为了减少由于系统抖动带来的骚扰,还需要实现抑制,例如服务器瞬间高负载,可能是正常的,我们可以不关注,只有持续一段时间的高负载才需要重视。

4) 恢复:运营人员不仅需要知道告警的产生,还需要知道告警什么时候恢复。

5) 合并:有时需要对同一时刻产生的多条告警进行合并,例如某个服务器同一时刻出现多个不同进程的告警,需要把这多个进程告警合并成为一条进程告警。

6) 相关性收敛:有时某个告警产生时,往往会伴随着其它告警。例如某个服务端进程不存在而产生进程告警时,会伴随着一些端口告警,对于一个智能的告警系统,应该只需要通知进程告警,而剩下的端口告警则会被收敛,作为该进程告警的子告警。当某个机架所有服务器都Ping不可达时,应该只需要发出一个机架掉电告警,机架上服务器的Ping不可达告警作为该机架掉电告警的子告警。

在质量需求如下,告警平台还需要具备如下特点

1)高可用:作为海量服务器监控的核心,告警平台的关键功能必须达到5个9的可用性,做到不误告警、不漏告警,不多告警,只有这样,才能让运维人员对告警平台产生信心,保持对告警的警惕性。因此,告警平台每个子模块都必须有完备的容灾、容错能力,单机故障时可平滑切换到备机。甚至当出现地震、海啸等不可抗拒自然灾害时,也可平滑实现异地容灾。

2) 易扩容:告警系统每时每刻都会有大量的原始告警产生,还需要进行各种屏蔽、去重、恢复等的判断,单机无法支撑如此海量的告警分析,支持平行扩展的分布式系统是必经之路。

3)易扩展: 随运营精细化需求,随时都可能需要支持新的告警类型,因此当有新的告警类型时,需要能非常快速方便地接入,复用整个告警屏蔽、收敛、去重、合并的通道。

3.3.2 架构设计

在架构上如何设计整个告警系统呢?因为整个告警环节多,链条长,为降低系统复杂度,提升可维护性,可以将整个告警流程进行多个维度的拆分:

1) 对告警流程纵向拆分,形成流水线。每个告警子模块接收上一个流程过来的数据,处理后,发送给下一个流程的告警子模块处理。

2)对每个流程环节的告警子模块横向拆分,每个流程环节都可以运行多个告警子模块,模块之间互相负载均衡。

3)对告警逻辑的拆分,每个告警子模块只做一件事,单一职责。例如,告警屏蔽模块,只处理屏蔽的处理,告警恢复模块,只做恢复的判断。

同时,引入消息队列,使告警子模块之间的通讯异步化,解除告警子模块之间的耦合。

最后,引入全局高可用Cache,所有内存数据均放到全局Cache,使每个告警子模块不带状态,形成无共享架构(Share Nothing Architecture)。

这样的设计带来很多好处:首先,每个告警子模块高内聚,低耦合,非常方便维护。其次,这种搭积木式构建的系统,功能易扩展,即使需要在告警流程中增加一个环节,只需要增加新的告警子模块,整个系统架构无须改造。而且,带个告警子模块都是无状态、负载均衡,可平行扩展的。某个环节出现性能瓶颈,多运行几个告警子模块即可,达到了监控海量服务器的能力。

3.3.3 相关性收敛设计

告警平台设计的另一个难点是告警的相关性收敛。假设某个机房掉电,必定出现大量的Ping不可达告警。相关性收敛需要对这种情况做出识别,收敛成一条大规模故障告警,而所有的Ping告警则作为该大规模故障告警的子告警。如果没有相关性收敛逻辑,运维人员将被淹没在大量告警中,根本无从判断故障。相关性收敛对于快速得到根因告警,提升告警处理效率具有重要意义。

实际运营中存在大量的相关性收敛逻辑,如端口告警可以被进程告警收敛,交换机下服务器Ping不可达告警可以被交换机Ping不可达告警收敛等。如果直接把这些收敛逻辑加入到告警流程,告警流程将非常复杂庞大,且难以维护。因此,告警相关性收敛可以采用“旁路反馈机制”,它的原理是由单独的模块分析相关性,再将结果反馈给收敛模块。收敛模块仅仅是一个收敛处理引擎,不负责分析相关性。这样避免了收敛分析串行化的性能和功能扩展的难题。要增加新的相关性规则,只需开发和平行部署新的分析模块即可,不会影响到当前的收敛策略。随运营经验的沉淀积累,以及业务的发展、监控手段的增加,可以逐渐加入新的相关性分析模块,使告警平台更加智能化。

(四)腾讯实践

基于上面的思路,腾讯网络平台部实现了针对海量服务器监控的系统Tencent Monitor Platform(简称TMP),具备支撑百万级服务器运营监控的能力。

采集层,通过Agent进行数据采集,打造跨越非扁平网络的数据上报通道,实现百万级Agent的自动化运营管理。

存储层,通过自研的分布式时间序列数据存储系统,实现海量监控数据的存储与快速查询。

告警层,基于无共享架构,纵向拆分告警流水线,使用消息队列异步通信,逻辑链解耦,实现了各种告警的合并、去重、相关性收敛,打造出一个高可用、易扩容、易扩展的告警平台。

欢迎关注公众帐号“鹅厂网事”,我们给你提供最新的行业动态信息、腾讯网络与服务器最接地气的干货分享,还有一大波互动交流板块和有奖活动正在筹备当中,需要您的热情参与哦,敬请期待!

注1:凡注明来自“鹅厂网事”的文字和图片等作品,版权均属于“深圳市腾讯计算机系统有限公司”所有,未经官方授权,不得使用,如有违反,一经查实,将保留追究权利;

注2:本文图片部分来至互联网,如涉及相关版权问题,请联系judithliu@tencent.com。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2015-09-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 鹅厂网事 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
对象存储
对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档