监控系统的组成与搭建

关键字:监控系统, statsd,influxdb,grafana

[TOC]

概念简介

statsd系统包括三部分:客户端(client)服务器(server)和后端(backend)。客户端植入于应用代码中(可以是一个现成的包或者自己集成的代码),将相应的metrics上报给statsd server。statsd server聚合这些metrics之后,定时发送给backends。backends则负责存储这些时间序列数据,并通过适当的图表工具展示。

statsd(server服务端)狭义来讲,其实就是一个监听UDP(默认)或者TCP的守护程序,根据简单的协议收集statsd客户端发送来的数据,聚合之后,定时推送给后端,如graphite和influxdb等,再通过grafana等展示。

需求

了解了监控系统的基本概念,在系统选型前,有必要先梳理我们的需求,只有明确需求,才能有合适的选择:

  • 业务指标类数据,需要表格展示,一般只关心最新状态
  • 时间序列数据,按时间轴展开分析,如各种系统延时
  • 开源,易扩展,方便二次开发
  • 能够直观展示告警数据

涉及到的模块

我们希望监控系统能采用开放性的架构,各个部件可以根据业务需要、开源社区发展程度进行调整。一般来说监控系统都有如下五个功能模块,我们将分别讨论。

  • 上报
  • 收集
  • 存储
  • 展示
  • 告警
  • 分析

数据的上报 —> 客户端

收据的上报的功能由客户端来实现,由非常多的开源的方案来实现,GitHub上收集了目前比较流行的语言的客户端实现,地址在此

stats的客户端植入与应用代码中,或者就是我们应用代码的一个模块或者一个集成好的第三方包,我们利用客户端,在我们需要的地方,记录想要监控的指标(API的请求次数,200的次数,4XX的次数等等)。记录的指标主要的分类有countertiming等,即数量指标与时间指标(数量指标比如,一分钟内有多少次请求数,时间指标比如一个请求的生命周期耗时多久)。

一般客户端通过UDP的通信方式,将数据扔到本机的8125端口。

我们以golang的一个简单包https://github.com/cactus/go-statsd-client为例,简单介绍下监控指标的记录与上报,完整的文档戳这里

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import (
"log"
"github.com/cactus/go-statsd-client/statsd"
)
func main() {
// first create a client
// The basic client sends one stat per packet (for compatibility).
client, err := statsd.NewClient("127.0.0.1:8125", "test-client")
// A buffered client, which sends multiple stats in one packet, is
// recommended when your server supports it (better performance).
// client, err := statsd.NewBufferedClient("127.0.0.1:8125", "test-client", 300*time.Millisecond, 0)
// handle any errors
if err != nil {
log.Fatal(err)
}
// make sure to clean up
defer client.Close()
// Send a stat
client.Inc("stat1", 42, 1.0)
}

从这个demo我们可以看到,客户端将指标发送到本机8125端口,具体的方法见详细文档。

数据的采集 —> 服务端

采集这方面已经有很多成熟的项目,如pythonPy-Statsd点击这里获得地址;如golang实现的gostatsd,都大同小异。但是,telegrafinfluxdata 的亲儿子,它支持 influxdb 特有的 keyfield 格式。毫无悬念的,既然上了 influxdb 的船,那就用 telegraf 。当然对于业务系统数据,可能会考虑直接往 influxdb 发送数据;telegraf 只负责采集系统级别的监控数据,当然telegraf自己全部负责了也是OK的。

存储 —> 后端时序数据库 (核心,优先选择)

这个监控系统最核心的是存储模块,数据的存储基本决定了展示和分析的形态。mysql不是很适合大量的时间序列类数据的频繁写入存储,所以为了监控系统的方方面面,存储必须足够高效 。要求存储系统 简单易用 ,且 表达能力 足够满足基本查询、分析需要。
influxdb 采用简洁而高效的 TSM 文件结构,查询语言基本与 sql 一致,而且用 golang 语言实现的程序效率和易用性都挺有保障。
另外一个选择是 graphite``,但由于其存储格式是固定时间间隔都要占坑,对于稀疏数据非常浪费空间;且每个 metric 都对应于一个独立的文件,同时写入多个 metric 会产生很多零碎的文件IO 操作,已经有不少关于这方面性能问题的吐槽。所以我选择 influxdb 作为存储系统。

展示 —> 后端界面服务

TICK 架构里的 Chronogra 作为展示模块,功能过于简单,无法满足需求。而另外一个成熟的 Grafana 项目,从 Graphite 时代就发展起来,拥有丰富的展示功能,强大而方便的可配置界面和插件系统,且可以批量创建管理展示配置,最关键的是与 influxdb 适配也非常成熟稳定(influxdata 的支持)。

告警 —> 后端警报服务

监控系统的成败就在于能否恰当地告警了。Grafana 自带报警功能,报警内容能在图标上直观地展示,这样出报警时可以方便查看报警情况,同时也方便运营同学平时有事没事 double check,避免因报警渠道阻塞而造成故障不能及时处理。不过 Grafana 的报警功能比较简单,只支持简单的阈值检查,所以这里还需要我们实现一些辅助分析,把复杂的报警需求转化成可以做简单阈值检查的指标书数据。
虽然TICK 架构包含了 Kapacitor 这一告警子系统,但它并不能直接支持展示,且使用的是自己的 dsl,虽然足够强大但表达能力毕竟还是受限, 但是可以作为一个备选项。

分析

分析模块可以自己定制,因为不同的项目需要分析的指标不同,侧重的维度也不同,建议直接手动代码实现。

通过上面的分析,我们基本确定好了选型的方案。

  • 客户端: python项目可以用pystatsdgolang项目可以用go-statsd-client
  • 服务端:直接采用telegraf即可
  • 后端:influxdb + grafana

具体实现环境的搭建

Docker方法的搭建与实现

直接使用集成好的docker镜像来搭建是最好不过的,这里我推荐的是samuelebistoletti/docker-statsd-influxdb-grafana。具体的搭建方案在hub上都有介绍,我在这里稍微翻一下,补充下。

Linux系统的docker环境的搭建请参考这里

特别是注意:切勿在没有配置 Docker APT 源的情况下直接使用 apt 命令安装 Docker.

需要的环境

  • Docker Image: 2.3.0
  • Ubuntu: 18.04
  • InfluxDB: 1.7.3
  • Telegraf (StatsD): 1.9.4-1
  • Grafana: 6.0.0

快速开始

使用如下的方式来进行第一次的容器加载,如果报权限错误,请使用sudo:

1
2
3
4
5
6
7
8
docker run --ulimit nofile=66000:66000 \
-d \
--name docker-statsd-influxdb-grafana \
-p 3003:3003 \
-p 3004:8888 \
-p 8086:8086 \
-p 8125:8125/udp \
samuelebistoletti/docker-statsd-influxdb-grafana:latest

可以使用latest版本,也可以使用changelog文件里列出的任何适合你的版本。

使用如下的命令来停止这个容器的运行, 同样如果有权限问题,请使用sudo, 下同:

1
docker stop docker-statsd-influxdb-grafana

使用如下命令运行这个容器:

1
docker start docker-statsd-influxdb-grafana

端口映射表

1
2
3
4
5
6
Host Container Service
3003 3003 grafana
3004 8888 influxdb-admin (chronograf)
8086 8086 influxdb
8125 8125 statsd --> telegraf

Grafana简介

当启动容器之后,可以代开这个地址来查看web显示界面 http://localhost:3003, 如果是远程服务,可以通过配置NGINX或者其他反向代理来开启web服务,下面是登陆时使用的默认用户名与密码,建议正式搭建时自己配置自己的docker镜像,修改此处信息,以免信息泄露。

1
2
Username: root
Password: root

在grafana上添加数据源

  1. 选择界面上的 Add data source
  2. 定一个名字
  3. 选择influxdb作为数据源来源的类型
  4. 选择你想看的指标并配置显示的界面然后保存即可
1
2
3
4
5
# 配置influxdb时需要的信息,同样也是这个镜像里的默认值,建议自己重新修改配置。
url: http://localhost:8086
Database: telegraf
User: telegraf
Password: telegraf

注意事项:Basic auth and credentials must be left unflagged. Proxy is not required.

Now you are ready to add your first dashboard and launch some query on database.

InfluxDB

Web 接口地址

可以打开这个地址来看 http://localhost:3004

1
2
3
Username: root
Password: root
Port: 8086
InfluxDB Shell (CLI) 命令行地址

如果不方面使用web接口地址,可以直接进入正在运行的docker内部查看。

  1. 连接docker容器, 运行这个shell命令 /bin/bash
  2. 输入influx来打开influxdb命令行界面,执行查询操作

关于这两步的补充信息:

  • 如何连接docker容器,首先使用sudo docker ps命令查看所有正在运行的docker容器,选择对应的容易,也就是我们自己这个容器,记住他的container ID, 然后运行sudo docker exec -it container_id bash就可以连接这个容器了。
  • 进入infuxdb之后关于他的一些基本用法,其实跟MySQL差不过,列出所有的数据库show databases,使用某个数据库use database_name, 查看这个数据库里所有的表,只需要在使用这个数据库后,输入show measurements即可,然后对每张表格的查询基本就和MySQL差不多了。

非Docker方法的搭建与实现

待续……