监控是分布式系统的重要组成部分。具有预警、故障排除、评估和决策等功能。1、监控系统的功能划分主机CPU告警称为监控;业务日志错误称为监控;APM条件触发器也称为监控。分布式系统错综复杂,随机收集统计指标也属于监控范畴。如何做到泛化,理清它们之间的关系,还需要下点功夫,不然揉在一起就很难拆解了。我习惯性的分为以下两种。在实际实现中,按照数据象限来划分系统比较合理:数据象限:按数据类型划分,大致可以分为:日志(logs)、监控(metrics)、调用链(tracing)。功能象限:从业务的角度可以分为:基础监控、中间件监控、业务监控无论是哪种监控系统,还涉及到以下模块流程:广度和效率。数据处理:数据整理、传输和存储。专名提取:大数据计算、中间结果生成和存储。数据显示:高价值、多功能显示。其中,特征提取只有在数据量达到一定程度才会启用,因为它的开发和运维成本一般不是小公司承担的。2.典型实现不同的监控模块关注的领域不同,职责不同。我个人倾向于独立设计,但需要一定程度的集成,主要是使用上的集成和优化。我将从几个典型的解决方案开始,并解释为什么它们应该单独设计而不是集中在一起。1、系统监控系统监控用于收集宿主机的监控状态(网络、内存、CPU、磁盘、内核等),包括大部分数据库和中间件的敏感指标。这些指标的典型特征是结构固定、指标项有限,最适合使用时序数据库存储。在指标收集方面,将优先考虑支持多样化的组成部分。例如telegraf支持所有的系统指标采集和大部分中间件和DB指标采集。注:这里特别推荐jolokia2组件,可以轻松实现JVM监控等功能。指标收集好后,强烈推荐使用Kafka做缓冲。除了抗重聚能力外,还可以方便数据共享(比如推送nginx日志到安全组)。指标进入消息队列后,会通过logstash过滤一份,整理成ES等NoSQL;另一个副本会按流量统计一些指标(比如QPS、平均响应时间、TP值等)。可以通过多种方式计算触发警报的聚合计算。回溯和叠加统计是常用的方法。在数据量特别大的情况下,需要先对索引数据进行预处理,否则再好的DB如influxdb也受不了。在展示方面,grafana是首选,因为它的颜值极高,并且支持通过iframe嵌入到其他系统中。它的缺点也很显着:支持类型有限(同比、环比、坡度不可用);报警功能不太好用。为什么?是不是觉得这个技术栈太长了?您实际上可以选择zabbix作为现成的解决方案组件。插件够用,小公司用起来其实最过瘾。但毕竟组件太集中,不方便拆解,发现问题也不能随意更换它的模块。这在架构上是一个致命的缺陷。到最后突然发现,实施成本竟然增加了。这就是为什么一定规模的公司不使用它的原因。自己开发一个也是可行的,但是并不简单。它要处理各种复杂的前端问题,并不是每个人都能做的漂亮。2.日志说到日志部分,大家首先想到的就是ELKB。但是我觉得ELKB的链接不稳定,不完整。我建议如下改造:可以看到系统监控的结构其实是差不多的,很多组件是可以复用的。不同的是数据量大,带宽往往一不小心就满了。日志的特点是体积大,无规则(nginx算是好公民),SLA要求也不是太高。这个时候收集部分会用到一些经过验证的日志收集组件。Logstash的资源控制不是很智能。为了避免争夺业务资源,flume和beats是更好的选择。同样的,消息队列缓冲区也是必须的,不然大量的Agent假死在业务端可不是闹着玩的。关于日志放置。不需要存储很多日志,比如研发同学开心敲出来的DEBUG日志,所以一定要有日志规范。Logstash根据这些规范进行过滤,并将其存储在ES中。日志量一般比较大,最好每天建立索引。之前的日志可以收集到日志堡垒机(就是一个非常非常大的磁盘),或者直接归档到HDFS。那么如何过滤业务日志的错误情况,比如有多少个XXX异常触发告警。在这种情况下,可以编写脚本,或者接收一段数据进行处理,然后生成监控项,丢给metricscollector。哈!再次回来。3、相对于普通的监控和日志,Tracing对调用链APM要复杂的多。除了大量的数据生成源,还必须有相应的业务组件来支持调用链聚合和展示。它的功能展示虽然简单,但却是监控系统中最复杂的模块。Google的论文《Dapper,一种大规模分布式系统跟踪基础设施》开启了调用链的流行。后续可以说是百家争鸣,直到最近几年才出现了OpenTracing这样的标准。在数据处理及后续展示方面,其技术点其实与监控技术类似,复杂性主要体现在调用链数据的采集上。目前的实现方式,如Pinpoint,直接使用javaagent技术修改字节码;还有类似cat的方法,直接encode。各有优缺点,但都需要解决以下问题:集合组件的异构性。开发语言可能包括java,也可能有多样化的golang组件。从前端埋点开始,nginx、中间件、db等环节都需要包含技术难点。异步、进程间上下文传递等采样,尤其是在海量调用的情况下,需要兼顾准确性和效率。Tracing的数据结构已经很烂了,这里就不多说了。各种实现也是各自为政,协议互不兼容,做了很多重复性的工作。为了解决不同分布式追踪系统API不兼容的问题,OpenTracing(http://opentracing.io/)规范诞生了。说白了就是一套接口定义,主流的调用链服务器实现都是兼容这个规范的,比如zipkin、jaeger。也就是说,只要你按照规范提供数据,就可以被zipkin采集和展示。OpenTracing有一统天下的趋势,它融合了Tracing、Log、Metrics的概念。看图吧,等到真正做的时候再发现也不迟(来自网络):值得一提的是,SpringCloud对它的支持比较全面(OpenTracingAPIContributions),但是依赖和版本呢非常混乱。建议参考后自行开发,一般使用“springbootstarter”技术,可以轻松编写上一个版本。至于《SpringCloud2》,离集成micrometer这个神器又近了一步,对于prometheus的集成也很不错。业务指标监控会省很多力气。上面说了这么多,我只说采集方面。标准的想法是非常正确的,不然每个公司都要写大量的集合组件,很无聊。至于国内大公司的产品,会不会主动向他们靠拢,我们拭目以待。在服务端,我们以Uber的Jaeger为例,说明一下服务端需要的通用组件:将数据批量发送给收集器Collector:接收jaeger-agent发送过来的数据,然后将数据写入后端存储。DataStore:后端存储设计为可插拔组件,支持将数据写入cassandra,ESQuery:接收查询请求,然后从后端存储系统中检索traces,并通过UI显示有,典型无状态系统,对等节点停机没有影响。4.分析预警上面的状态图不止一次提到了流计算。这不需要整个SparkStreaming。从Kafka接收一段数据,自己处理也叫流计算。选择最新的Kafkastream也是无法避免的选择。重要的是聚合聚合聚合,重要的事情说三遍。一般计算一些QPS、RT等,也就是纯计数;或斜率,即增长和下降的速度;比较复杂的包括TP值(多少%的请求在XX秒内得到响应),调用链服务拓扑图和日志异常统计都可以在这里计算。好在流计算的API比较简单,调试起来比较费力。分析后的数据是经过处理的数据,应单独存储。当然,如果量少,也可以和原始数据混合。可以评估分析数据的数量。比如5秒1条数据固定为每天17280条。预警模块读取分析后的数据(原始数据太大),计算量也很大。那么分析出来的统计数据是用来做什么的呢?一方面是预警;另一部分是显示。1)预警以我设计的一个原型为例,一个metric的运行一般有以下内容:在一个时间间隔内,某个监控项触发阈值XX次。触发动作包括:大于、小于、平均值大于、平均值小于、环比大于、环比小于、同比大于、同比小于、自定义表达式为数值数组,多个监控项的交互层级一般根据企业文化划分。聚合配置六层就够了,表示阈值触发或者聚合触发,比如在5分钟的时间跨度内出现5次,就认为是惩罚。触发警报后,将发送电子邮件、电话、短信和网络钩子,仅供参考。这只是配置的冰山一角。各种起跑动作再做一遍,会浪费很多脑细胞。2)显示visualjs库很多,但是工作量普遍比较大。但是也没有办法,简单的用grafana配置一下,如果比较复杂就需要自己动手了。我这里有两张简单的grafana图,大家可以参考一下:【系统监控】【jvm监控部分】5.总结总体来说,整个系统就是收集、处理和应用这三类数据(logs、metrics、trace)。其中一些组件的经验可以分享,但收集部分和应用部分有很大的不同。试图用一张图来概括,但是只能看到涉及到哪些组件,只看图是模棱两可的。每种结构具体的数据流向和处理方式都不一样,这也是我一直强调分而治之的原因。但在用法上,最好不要相差太大。不管后端架构有多复杂,一个整体的外观会让产品更加清晰。你现在的工作也集中在这里吗?3.部分组件通过了解以上内容可以了解我们习惯的方面监控系统的所有模块都已拆解,您可以轻松更换组件。比如beat替换flume,cassandra替换ES……下面我会列举一些常用的组件。如有遗漏,请补充。1、数据采集组件telegraf用于采集监控项。它是influxdata家族的一员,是用Go编写的代理程序。它可以收集系统和服务统计信息并将它们写入各种数据库。支持的类型可谓非常广泛。Flume主要用来收集日志数据,apache家族。Flume-og和Flume-ng的版本差别很大。它们是一个高可用、高可靠、分布式的海量日志收集、聚合和传输系统。Flume支持在日志系统中自定义各种数据发送器来收集数据;同时,Flume提供了简单处理数据并写入各种数据接收器的能力(可定制)。LogstashLogstash是一款开源的日志收集管理工具,elastic家族的一员。功能类似于flume,但是很贪婪的占用资源。使用时建议独立部署。功能丰富,支持Ruby定义过滤条件。StatsDnode开发,采用udp协议传输,专门用于采集数据,采集数据后会发送给其他服务器进行处理。类似于电报。CollectDcollectd是一个守护进程,定期收集系统和应用程序性能指标,并提供以不同方式存储这些指标值的机制。2.可视化独立的可视化组件比较少,但是解决方案一般都会包含一个web端,grafana这种比较专注的不多。Grafana以展示为主,价值高,集成了非常丰富的数据源。通过简单的配置,就可以获得非常专业的监控地图。3.有很多很少用到的存储,你可以看这里:GrafanaPlugins-extendandcustomizeyourGrafana.InfluxDBinfluxfamilyproducts。Influxdb是一个开源的分布式时序、时间和指标数据库,使用go语言编写,无需外部依赖。支持的数据类型非常丰富,性能高。使用单节点时不收费,集群收费。OpenTSDBOpenTSDB是一个时间序列数据库。它实际上不是数据库。单个OpenTSDB不能存储任何数据。它只是一层数据读写服务。更准确的说,它只是建立在Hbase之上的一层数据读写服务。可以承受海量的分布式数据。Elasticsearch可以存储监控项,也可以存储日志,还可以存储trace关系。支持丰富的聚合功能,可以实现非常复杂的功能。但是如果时间跨度太大,设计的索引和分片太多,ES容易混淆。4.方案Open-Falcon是小米出品的。它实际上包括代理、处理和存储等模块,并有自己的仪表板。这是一个解决方案,我喜欢它。但是目前很少有人用,你也知道国内开源的东西很生气:公司吹牛高大上,社区却用的是半成品。GraphiteGraphite本身并不收集度量数据,而是像数据库一样,通过其后端接收度量数据,然后实时查询、转换和组合这些度量数据。Graphite支持内置的Web界面,允许用户浏览指标和图表。它最近发展得很好,经常和Collectd搭配使用。Grafana也默认将其集成为数据源。Prometheusgolang开发,发展趋势不错。它的灵感来自谷歌的borgmon监控系统,该系统于2015年正式发布,相对年轻。普罗米修斯的目标是远大的,从它的名字就可以看出——普罗米修斯。另外,SpringCloud对它的支持也很好。5、传统的监控图形仍然是使用AWT或者GD来渲染。总觉得这些东西快被淘汰了。Zabbix用的比重非常大,大到不用我过多介绍。但是随着节点和服务的增加,在1k左右就会遇到瓶颈(包括开发和定制瓶颈)。一般来说,小公司用的很好,大公司用的很差。Nagios也比较老了,长期客户很多。它的安装配置比较复杂。不足的功能比较具体,个人不是很喜欢。GangliaGanglia的核心由gmond、gmetad和一个web前端组成。主要用于监控系统性能,如:cpu、mem、硬盘利用率、I/O负载、网络流量情况等,通过曲线很容易看到各个节点的工作状态,从而进行调整而合理分配系统资源,提高系统的整体性能具有重要作用。Centreon是老式的,它与nagios无缝协作。你还在用吗?6.APMAPM是一个比较特殊的领域,实现也很多。附:支持OpenTracing的APM列表CAT其实美团的东西很少,大部分都是用review来做外观的。CAT作为美团点评的基础监控组件,已经广泛应用于中间件框架(MVC框架、RPC框架、数据库框架、缓存框架等),提供系统性能指标、健康状态、基础告警等。它更尽职尽责,但它是非常侵入性的。如果你的代码量很大,那将是一场噩梦。技术实现比较老,但是控制力强。Pinpointpinpoint是github上开源的APM监控工具。它是用Java编写的,用于大规模分布式系统监控。agent的安装是非侵入式的,即使用了java的仪器技术,注定是基于java的。SkyWalking有华为的标签,类似于pinpoint,使用探针采集数据,2015年工作,使用ES作为存储。进入Apache,它支持Opentracing。Zipkin哦,zipkin也是这么走的,不过zipkin是支持opentracing协议的,用着不爽可以换掉,挺大方的。由jaegergolang开发,Uber产品,小巧玲珑,支持OpenTracing协议。它的Web端也很漂亮,提供ES和Cassandra后端存储。7.其他Datadog在此提供了独特的收费解决方案。为什么?因为它做得很漂亮。没有办法控制外观。另外,还凭良心写了很多具体的实现代码和文档,质量非常高。如果你想开发自己的集合,不妨阅读一下。监控系统的复杂性就在于复杂性。如何理清关系,给用户一个合理的思维模式才是重中之重。这就是所谓的产品体验优先。从整个发展过程可以看出,标准化是对技术最好的提升,但也必须经历一个群魔乱舞的时代。既得利益者会维护自己的壁垒,拒绝接受和开放,然后突然发现自己的东西已经落伍了,跟不上时代了。
