小米开源监控系统OpenFalcon应对高并发7种手段前端
原创 2016-04-01 秦晓辉 高可用架构 编者按:本文是秦晓辉在 3 月 27 日数人云“百万并发”活动的演讲,受权「高可用架构」首发。转载请注明来自高可用架构公众号「ArchNotes」。golang
秦晓辉,小米运维研发技术负责人,互联网公司监控解决方案 OpenFalcon 主程,国内第一套开源 PaaS 平台 DINP 主程,企业级业务监控 Minos 做者,Gopher,现负责小米运维平台的搭建。关注运维自动化、PaaS 领域。算法
今天给你们简单介绍一下 OpenFalcon 应对高并发的一些手段。OpenFalcon 是一个监控系统,来自于小米的运维团队,OpenFalcon 主要针对运维架构师、DevOP 及关注高并发的研发人员。小米在使用 OpenFalcon 的过程中,每一个周期(5 分钟)大约有 1 亿条数据汇报上来。数据库
下面我首先会对 OpenFalcon 作一个简单介绍,而后再介绍小米在高并发场景 7 种应对的手段,包括怎么作数据采集、转发、分片、报警等内容。后端
(OpenFalcon 架构,点击图片可全屏缩放)浏览器
OpenFalcon 简介缓存
监控系统是整个运维环节,乃至整个产品生命周期中最重要的一环。服务器
当公司刚刚起步,业务规模较小,运维团队也刚刚创建的初期,选择一款开源的监控系统,是一个省时省力,效率最高的方案。微信
以后,随着业务规模的持续快速增加,监控的对象也愈来愈多,愈来愈复杂,监控系统的使用对象也从最初少数的几个 SRE,扩大为更多的 DEVS,SRE。这时候,监控系统的容量和用户的“使用效率”成了最为突出的问题。网络
OpenFalcon 来自于小米的运维团队,在 2014 年初开发,大约开发了半年左右第一个版本上线,以后一直在线上稳定运行,后来咱们成立了 OpenFalcon 社区。
如今有不少公司正在使用 OpenFalcon,像美团、金山云、京东金融、赶集、宜信、快网等。
BAT 这种大公司目前还没了解到是否使用 OpenFalcon,他们大多使用自研系统。
OpenFalcon 官网是 http://open-falcon.org/ ,文档地址是 http://book.open-falcon.org/ ,感兴趣的同窗的能够进一步访问了解。
OpenFalcon 是在这样一个场景下产生,当时小米有三套 Zabbix,每套大约能够支撑 2,000 台机器左右。当时有 6,000 台机器,因此搭建了 3 套 Zabbix。另外内部还有 1 套业务监控系统,内部叫 PerfCounter,负责业务性能指标监控。
因为 4 套监控系统维护起来比较麻烦,因而就有了开发这么一个大一统的解决方案,也就是 OpenFalcon 的想法。
(高可用小编:看来牛人偷懒,永远是强大系统产生的源动力)
OpenFalcon 其余部分特性还包括:
水平扩展能力:支持每一个周期上亿次的数据采集、告警断定、历史数据存储和查询
高可用:整个系统无核心单点,易运维,易部署,可水平扩展
开发语言: 整个系统的后端所有 golang 编写,portal 和 dashboard 使用Python 编写
OpenFalcon 在高并发场景的 7 种应对手段
对于监控系统来讲,包含几个核心功能:数据采集、历史数据存储、报警,最后是绘图展现及数据挖掘。
数据采集
这一块咱们但愿作一个大一统的东西,所以要采集不少监控指标,好比 Linux 自己的监控指标,像 CPU、内存、网卡、IO 等,一些硬件指标,好比风扇的转速、温度等等,再加上一些开源软件如 MySQL,Nginx,OpenStack,HBase 等监控指标。
公司内部有不少产品线,每个服务运行情况都但愿采集到,好比中间层服务开了一些 RPC 端口,每个 RPC 端口在服务过程当中,latency 是多少,QPS 是多少,咱们都但愿了解到。
因此须要覆盖不少监控指标,监控团队刚开始只有两我的,不可能把全部监控指标都采集到——人力不行、技术水平也达不到。
因此咱们须要共建监控数据,让专业的人干专业的事。
DBA 同窗对 MySQL 比较熟,那他们去采集 MySQL 相关指标,分布式团队同窗去采集 HBase 或 Hadoop 等指标,网络组同窗去采集交换机路由器指标。
而做为监控团队要作的,就是制订一个规范。制定一个数据进来的机制,而后公司开发人员和运维人员按照规范去推送数据。
数据收集没有采用拉的方式,由于太多数据源,做为一个 Client 去链接源端,采集数据,再关闭链接,会产生不少 time_wait 状态链接,其吞吐必然是不高,因此要把本身作成 Server 端。如今每一个周期有 1 亿多条数据。
这个周期简单解释一下,监控数据是一个持续上报,好比 Linux 一些基本监控项一分钟一次采集以后上报,下一分钟再采集再上报。一些像业务监控有 3 分钟的,有 5 分钟的。
所以周期是指数据量是 5 分钟之内,有上报动做的数据。
数据有不少要 Push 到 Server 端,Server 端最前端组件是 Transfer,Transfer 接收到数据后要把它转发给后面两个组件,一个是 Graph(用来作绘图),一个是 Judge(用来作报警判断)。
首先对每个后端实例建立一个 Queue 出来,好比 20 个 Graph 实例,60 个 Judge 实例,为每一个实例建立一个 Queue,每一个 Transfer 内存中有 80 个 Queue,
当一条监控数据过来以后,须要判断数据发到哪个实例,而后放到这个实例对应 Queue。Transfer 接收数据 RPC 逻辑很是简单,数据拿到后放到 Queue 就立马返回。
Agent 到 transfer,transfer 到 judge,judge 到 Redis,Redis 到 alarm,报警链路比较长,若是但愿尽快触发报警,链路每个环节都但愿比较快速处理,用 Queue 方式,Transfer 吞吐特别大,不会拖慢整个链路。
数据放在 Queue 中有一个问题,若是不及时转发,好比后端 load 比较高或者挂了,Queue 数据就会堆积,超过内存就会 crash,因此作了一个简单保护措施,将 Queue 设成定长,超过 Queue 长度,数据就放不进来。
数据 Push 到 Queue 后,有一个专门对 Queue 读入 worker,读到了以后转发。转发这个动做由一堆写 worker 完成,这里 worker 是指 goroutine,如此这般,一堆 goroutine 协同工做,来提升转发性能。
一致性哈希分片
这么多数据上来不可能由一台机器处理,所以作了一个数据分片,即一个机器只处理一部分数据,报警数据是由 Judge 作分片,绘图数据由 Graph 作分片,这两个都是使用一致性哈希。
一致性哈希分片有一个问题,就是扩缩容比较麻烦,数据打到某个 judge 以后,就会一直打到这个 judge。
当列表发生变化时候,因为一致性哈希算法,原来打到一台 judge 实例的数据就会打到另一个 Judge 实例,因此 Judge 必定要保证没有状态,这样才能方便扩缩容。
状态标记
其实说它没有状态也不太合适,judge 内存里也存了几个点。好比某一台机器 cpu.idle 数据上来以后,连续 3 ~ 5 次达到一个特定阀值才去报警,而不是达到阀值立马报警。像 CPU,是一直都忙碌状态才去报警,Judge 判断的时候它是判断多个点。
产生报警以后,还有一些后续处理,好比对这个报警事件作一个判断,上次产生事件是什么状态,他是第几回报警,是否是达到了最大报警次数不能再报了,避免重复报警给处理人员形成干扰。通常你们都设置报警 3 次。
所以报警事件须要记录一个状态,标记是否健康,若是有问题,记录当前是第几回。Judge 状态存在数据库,虽然 1 亿条数据上来,实际上报警数据很少,可能只有 10 万条数据级别,所以能够存入数据库,这样 Judge 就剥离了报警事件状态。
虽然 Judge 内存当中还存一些前面所说数据状态,但也不是一个大问题。由于监控数据是源源不断上来,即便丢掉一些状态,新的 Judge 实例很快就会又填充数据。
扩容
一致性哈希对扩容不是很友好,好比 20 台 Graph 的机器若是变成 40 台,势必有老的 Graph 实例的一部分数据打到新的 Graph 上,所以咱们作了一个自动数据迁移。
这个自动迁移是因为一致性哈希形成的问题,若是用映射表作分片,在映射表这统一维护数据和 graph 实例对应关系,扩容就简单不少。
当数据上来后,要判断这个数据是否是触发了报警策略,策略有不少种,好比咱们如今系统中有几千上万条。
上来一条数据以后,要判断这个数据跟哪一条策略相关,而后再判断阀值是多少,是否是要触发报警。
咱们选择去数据库同步全部报警策略列表,由于策略列表整个公司不会特别多,虽然数据量多,可是策略不是特别多,好比只有几千条或者几万条。
在策略数据库作了一个简单索引,方便数据上来以后快速定位策略,而后根据阀值看是否要须要报警处理。
为了加快策略断定,须要知道近期一些历史数据,历史存在 Judge 内存中,这样获取速度相对来讲快一些。
第一个版本作测试时没有放到内存中,当时用了 56 个 Redis 实例,每一个实例大概有 3,000 QPS,那时上的量不大,仍然达到了一个这么高的 QPS。因为并发高,把数据放到 Redis 中并非一个很好的解决办法,后来就把它放到了Judge 内存里。这样处理起来就快不少。
报警状态也存在 Judge 内存及 DB。若是每一个报警判断都去访问 DB 比较耗时,因此就加载到 Judge 内存,至关与缓存的机制,内存没有再去 DB 加载。在 Judge 重启的时候,内存没有数据,这时报警状态的判断须要去 DB 加载,而后再读到内存里。
时间序列数据自动归档
报警数据存储采用 RRD,RRD 比较有名。大量开源监控软件存储时间序列数据都选用 RRD。
RRD 最大的优势是自动归档。监控数据有一个特色,不须要关心历史监控数据具体的值,只需知道当时的趋势便可。
最新 6 个小时可能有看原始值需求。可是最近 3 天 及 1 个月原始值的需求就很小。并且那个点特别多,一分钟 1 个点,一天有 1440 个点。若是加载 1 个月浏览器不崩才怪。
因为对历史点只要能看到趋势就行。所以监控数据特别须要归档功能。好比一个小时的数据归档为一个点,RRD 能够帮咱们作这个事情。
RRD 优化:延迟合并写入
RRD 默认操做性能比较差,它的逻辑是打开 RRD 文件,而后去 seek,write,seek,write,最后 close 文件句柄。一个监控指标对应一个 RRD 文件,好比这个机器上面处理了大约 200 万个监控指标,实际上就有 200 万个 RRD 的文件。
每次写入数据的时候,打开这个 RRD 文件,读头部信息,包含一些 meta 信息,记录了归档策略、数据类型之类数据,而后去作写入操做。
若是每个数据上来以后都作这个操做,RRD 读写会形成特别大的 IO。虽然如今磁盘都是 SSD,但因为 IO 居高不下,因而作了一个延迟写入的优化。
如今数据都是 1 分钟上报一次,可能有的数据 10 秒或 30 秒上报一次。并非上报上来立马打开 RRD 文件写入,而是等 10 分钟或者 30 分钟,在内存中缓存一段时间,缓存 30 个点或者 60 个点,一次性把文件打开,一次性写入再关闭,这样能够减小 RRD 文件打开的次数,让 IO 下降一些。
咱们根据缓存的时间,好比缓存半个小时,再按照半个小时时间长度来作数据打散,好比如今半个小时是 1,800 秒,举个例子,1,800 秒把它作成 1,800 个槽位,每一个数据上来以后平均分散到 1,800 个槽位当中,写的时候慢慢地写,这样作了一个打散操做,避免让 IO 出现一些峰值。
报警事件量一般不是特别大,但个别时候会比较大——触发一些大面积报警的时候,好比某一个核心交换机挂掉了,会产生特别大的报警。
好比服务依赖于上游某几个服务,上游服务挂了,全部下游服务都报警。若是核心交换机挂了,不少核心服务都受影响,核心服务受影响以后,下游不少服务就产生报警,这样产生一个大面积报警。但一般状况下,报警量都是一个很平稳的一个量。
当大面积报警出现时,咱们仍然是应用 Queue 机制,用 Queue 来抹平峰值。
报警的分级处理
咱们将报警进行分级,从 P0、P1 一直到 P5,P0 最高。
基于优先级的分级策略
P0、P1 发短信发邮件,而且是收到报警当即发; P2 这个级别发短信不是当即发,而是作一个报警合并; P三、P4 那些低级别就作报警合并,同时不发短信,只发邮件。
咱们对报警事件作一个分级,每个级别就对应 Redis 里面一个Queue。利用 Redis BRPOP 简单实现按照优先级处理报警事件,即先处理 P0,再处理 P一、P2 顺序。
系统自己可能链路比较长,每一个链路都但愿可以扛住高并发,实际上在系统开发过程中,咱们依赖于其余基础设施,好比内部有 SMTP 服务器来发送邮件,有短信通道来发送短信,可是这些接口扛不住很大的并发。
当要系统依赖调用几个并发能力较差的接口,最好作一个限流。
有一个专门的模块 Sender 发送报警邮件或者报警短信,它发送时候能够给它配置一个 Worker 数量,你们能够理解成最多有多少个线程来调用发送接口。这样就能够保护后端发送接口,不至于把它打挂。
总结
回到今天的议题“百万并发”,总结咱们在设计 OpenFalcon 用到的技术。
分片:一台机器抗不住就分红多台机器,数人云是一个 PaaS 平台,PaaS 平台很容易作扩容,原来三百台实例如今作三千台,在页面上按键按一下,10 秒就可让 3000 台实例起来,作 3000 个分片。
队列:有时候产生一些峰值,咱们不但愿被峰值打垮,因而用队列作缓冲,这个系统有多个地方用到队列,好比 transfer 内存中构建了多条队列,报警事件使用 Redis 作队列服务。
索引:索引能够加快查询速度。
限流:后端的接口抗不住压力的时候会作限流。
这只是几个简单的、很普适的手段,没有炫耀那些高精尖、你们不太能理解及很难借鉴的东西,但愿能给你们在应对高并发时候提供一些参考,谢谢你们!
相关精彩文章
基于 Locust、Tsung 的百万并发秒杀压测案例 5 人技术团队开发 Go Web 项目的 9 条教训 小米抢购限流峰值系统「大秒」架构解密
想关注更多高并发技术,请订阅公众号获取更多文章。转载请注明来自高可用架构「ArchNotes」微信公众号及包含如下二维码。
高可用架构 改变互联网的构建方式