专栏第7期我给你讲解了监控系统的实现原理,先来简单回顾一下,一个监控系统的组成主要涉及四个环节:数据收集、数据传输、数据处理和数据展示。不同的监控系统实现方案,在这四个环节所使用的技术方案不同,适合的业务场景也不一样。

目前,比较流行的开源监控系统实现方案主要有两种:以ELK为代表的集中式日志解决方案,以及GraphiteTICKPrometheus等为代表的时序数据库解决方案。接下来我就以这几个常见的监控系统实现方案,谈谈它们的实现原理,分别适用于什么场景,以及具体该如何做技术选型。

ELK

ELK是Elasticsearch、Logstash、Kibana三个开源软件产品首字母的缩写,它们三个通常配合使用,所以被称为ELK Stack,它的架构可以用下面的图片来描述。


(图片来源:https://cdn-images-1.medium.com/max/1600/1*mwSvtVy_qGz0nTjaYbvwpw.png

这三个软件的功能也各不相同。

这种架构因为需要在各个服务器上部署Logstash来从不同的数据源收集数据,所以比较消耗CPU和内存资源,容易造成服务器性能下降,因此后来又在Elasticsearch、Logstash、Kibana之外引入了Beats作为数据收集器。相比于Logstash,Beats所占系统的CPU和内存几乎可以忽略不计,可以安装在每台服务器上做轻量型代理,从成百上千或成千上万台机器向Logstash或者直接向Elasticsearch发送数据。

其中,Beats支持多种数据源,主要包括:

Beats将收集到的数据发送到Logstash,经过Logstash解析、过滤后,再将数据发送到Elasticsearch,最后由Kibana展示,架构就变成下面这张图里描述的了。


(图片来源:https://logz.io/wp-content/uploads/2018/08/image21-1024x328.png

Graphite

Graphite的组成主要包括三部分:Carbon、Whisper、Graphite-Web,它的架构可以用下图来描述。


(图片来源:https://graphiteapp.org/img/architecture_diagram.png

也就是说Carbon负责数据处理,Whisper负责数据存储,Graphite-Web负责数据展示,可见Graphite自身并不包含数据采集组件,但可以接入StatsD等开源数据采集组件来采集数据,再传送给Carbon。

其中Carbon对写入的数据格式有一定的要求,比如:

servers.www01.cpuUsage 42 1286269200
products.snake-oil.salesPerMinute 123 1286269200
[one minute passes]
servers.www01.cpuUsageUser 44 1286269260
products.snake-oil.salesPerMinute 119 1286269260

其中“servers.www01.cpuUsage 42 1286269200”是“key” + 空格分隔符 + “value + 时间戳”的数据格式,“servers.www01.cpuUsage”是以“.”分割的key,代表具体的路径信息,“42”是具体的值,“1286269200”是当前的Unix时间戳。

Graphite-Web对外提供了HTTP API可以查询某个key的数据以绘图展示,查询方式如下。

http://graphite.example.com/render?target=servers.www01.cpuUsage&
width=500&height=300&from=-24h

这个HTTP请求意思是查询key“servers.www01.cpuUsage”在过去24小时的数据,并且要求返回500*300大小的数据图。

除此之外,Graphite-Web还支持丰富的函数,比如:

target=sumSeries(products.*.salesPerMinute)

代表了查询匹配规则“products.*.salesPerMinute”的所有key的数据之和。

TICK

TICK是Telegraf、InfluxDB、Chronograf、Kapacitor四个软件首字母的缩写,是由InfluxData开发的一套开源监控工具栈,因此也叫作TICK Stack,它的架构可以看用下面这张图来描述。


(图片来源:https://2bjee8bvp8y263sjpl3xui1a-wpengine.netdna-ssl.com/wp-content/uploads/Tick-Stack-Complete.png

从这张图可以看出,其中Telegraf负责数据收集,InfluxDB负责数据存储,Chronograf负责数据展示,Kapacitor负责数据告警。

这里面,InfluxDB对写入的数据格式要求如下。

<measurement>[,<tag-key>=<tag-value>...] <field-key>=<field-value>[,<field2-key>=<field2-value>...] [unix-nano-timestamp]

下面我用一个具体示例来说明它的格式。

cpu,host=serverA,region=us_west value=0.64 1434067467100293230

其中,“cpu,host=serverA,region=us_west value=0.64 1434067467100293230”代表了host为serverA、region为us_west的服务器CPU的值是0.64,时间戳是1434067467100293230,时间精确到nano。

Prometheus

还有一种比较有名的时间序数据库解决方案Prometheus,它是一套开源的系统监控报警框架,受Google的集群监控系统Borgmon启发,由工作在SoundCloud的Google前员工在2012年创建,后来作为社区开源项目进行开发,并于2015年正式发布,2016年正式加入CNCF(Cloud Native Computing Foundation),成为受欢迎程度仅次于Kubernetes的项目,它的架构可以用下图来描述。


(图片来源:https://prometheus.io/assets/architecture.png

从这张图可以看出,Prometheus主要包含下面几个组件:

它的工作流程大致是:

Prometheus存储数据也是用的时间序列数据库,格式如下。

<metric name>{<label name>=<label value>, …}

比如下面这段代码代表了位于集群cluster 1上,节点IP为1.1.1.1,端口为80,访问路径为“/a”的http请求的总数为100。

http_requests_total{instance="1.1.1.1:80",job="cluster1",location="/a"} 100

讲到这里,四种监控系统的解决方案都已经介绍完了,接下来我们对比一下这四种方案,看看如何选型。

选型对比

我们从监控系统的四个环节来分别对比。

1. 数据收集

ELK是通过在每台服务器上部署Beats代理来采集数据;Graphite本身没有收据采集组件,需要配合使用开源收据采集组件,比如StatsD;TICK使用了Telegraf作为数据采集组件;Prometheus通过jobs/exporters组件来获取StatsD等采集过来的metrics信息。

2. 数据传输

ELK是Beats采集的数据传输给Logstash,经过Logstash清洗后再传输给Elasticsearch;Graphite是通过第三方采集组件采集的数据,传输给Carbon;TICK是Telegraf采集的数据,传输给InfluxDB;而Prometheus是Prometheus Server隔一段时间定期去从jobs/exporters拉取数据。可见前三种都是采用“推数据”的方式,而Prometheus是采取拉数据的方式,因此Prometheus的解决方案对服务端的侵入最小,不需要在服务端部署数据采集代理。

3. 数据处理

ELK可以对日志的任意字段索引,适合多维度的数据查询,在存储时间序列数据方面与时间序列数据库相比会有额外的性能和存储开销。除此之外,时间序列数据库的几种解决方案都支持多种功能的数据查询处理,功能也更强大。

alias(sumSeries(stats.openapi.profile.*.API._comments_flow.total_count,"Total QPS")
SELECT 100 - usage_idel FROM "autogen"."cpu" WHERE time > now() - 1m and "cpu"='cpu0'
100 - (node_cpu{job="node",mode="idle"}[1m]) 

4. 数据展示

Graphite、TICK和Prometheus自带的展示功能都比较弱,界面也不好看,不过好在它们都支持Grafana来做数据展示。Grafana是一个开源的仪表盘工具,它支持多种数据源比如Graphite、InfluxDB、Prometheus以及Elasticsearch等。ELK采用了Kibana做数据展示,Kibana包含的数据展示功能比较强大,但只支持Elasticsearch,而且界面展示UI效果不如Grafana美观。

总结

以上几种监控系统实现方式,所采用的技术均为开源的,其中:

从对实时性要求角度考虑,时间序列数据库的实时性要好于ELK,通常可以做到10s级别内的延迟,如果对实时性敏感的话,建议选择时间序列数据库解决方案。

从使用的灵活性角度考虑,几种时间序列数据库的监控处理功能都要比ELK更加丰富,使用更灵活也更现代化。

所以如果要搭建一套新的监控系统,我建议可以考虑采用Graphite、TICK或者Prometheus其中之一。不过Graphite还需要搭配数据采集系统比如StatsD或者Collectd使用,而且界面展示建议使用Grafana接入Graphite的数据源,它的效果要比Graphite Web本身提供的界面美观很多。TICK提供了完整的监控系统框架,包括从数据采集、数据传输、数据处理再到数据展示,不过在数据展示方面同样也建议用Grafana替换掉TICK默认的数据展示组件Chronograf,这样展示效果更好。Prometheus因为采用拉数据的方式,所以对业务的侵入性最小,比较适合Docker封装好的云原生应用,比如Kubernetes默认就采用了Prometheus作为监控系统。

思考题

通过我今天的讲解,你应该知道了Graphite、TICK以及Prometheus存储监控数据都采用了时间序列数据库,它们在存储和性能上有什么不同之处吗?

欢迎你在留言区写下自己的思考,与我一起讨论。

评论