本节将会讲解如何使用 Telegraf(StatsD) + InfluxDB + Grafana 搭建一套完整的监控系统。
Telegraf 是一个使用 Go 语言开发的代理程序,可收集系统和服务或者其他来源(inputs)的数据,并将其写入 InfluxDB(outputs)数据库,支持多种 inputs 和 outputs 插件。StatsD 是一个使用 Node.js 开发的网络守护进程,通过 UDP 或者 TCP 方式收集各种统计信息,包括计数器和定时器等。
InfluxDB 是一个使用 Go 语言开发的开源的分布式时序、事件和指标数据库,无需外部依赖,其设计目标是实现分布式和水平伸缩扩展。
Grafana 是一个使用 Angular + Go 语言开发的开源的、功能齐全的、漂亮的仪表盘和图表的编辑器,可用来做日志的分析与展示曲线图(如 api 的请求日志),支持多种 backend,如 ElasticSearch、InfluxDB、OpenTSDB 等等。
工作流程:Telegraf 将 StatsD(inputs)和 InfluxDB(outputs)结合起来,即发往 StatsD 的数据,最终通过 Telegraf 写入了 InfluxDB,然后 Grafana 读取 InfluxDB 的数据展示成图表。
我们使用 Docker 一键启动 Telegraf(StatsD)+ InfluxDB + Grafana,节省搭建环境的时间。
$ docker run -d \ --name docker-statsd-influxdb-grafana \ -p 3003:3003 \ -p 3004:8083 \ -p 8086:8086 \ -p 22022:22 \ -p 8125:8125/udp \ samuelebistoletti/docker-statsd-influxdb-grafana:latest
端口映射关系如下:
Host Container Service ----------------------------------- 3003 3003 grafana 3004 8083 influxdb-admin 8086 8086 influxdb 8125 8125 statsd 22022 22 sshd
容器启动后,浏览器访问 localhost:3004(以下称为 influxdb-admin),如下所示:
InfluxDB 的基本概念如下:
InfluxDB 采用了类 SQL 的查询语法,例如:
我们在 Query 中输入:
show databases
查询结果如下:
_interal 是 InfluxDB 内部使用的数据库,telegraf 是我们当前 Docker 容器启动后默认创建的测试数据库。
用浏览器打开 localhost:3003,如下所示:
输入用户名 root 和密码 root 登录,进入初始化配置页,单击 “Add data source”,如下填写:
单击 “Save & Test” 保存配置。目前配置好了 Grafana 默认的 datasource 是名为 api 的 InfluxDB,接下来创建测试代码,产生测试数据。
node-statsd 是一个 statsd 的 Node.js client。创建以下测试代码:
const StatsD = require('node-statsd') const statsdClient = new StatsD({ host: 'localhost', port: 8125 }) setInterval(() => { const responseTime = Math.floor(Math.random() * 100) statsdClient.timing('api', responseTime, function (error, bytes) { if (error) { console.error(error) } else { console.log(`Successfully sent ${bytes} bytes, responseTime ${responseTime}ms`) } }) }, 1000)
运行以上代码,每一秒钟会产生一个 0~99 之间的随机值(模拟响应时间,单位为毫秒),发送到 StatsD,StatsD 会通过 Telegraf 将这些数据写入 InfluxDB 的 telegraf 数据库。
回到 influxdb-admin,单击右上角的下拉菜单切换到 telegraf 数据库,然后输入 show measurements 查看已经存在 api 表了,然后输入:
show measurements
select * from api
可以看出 api 表有以下几个字段:
回到 Grafana,单击左上角 Grafana 图标的下拉菜单,单击 Dashboards 回到仪表盘页继续完成配置,单击 “New dashboard”,然后单击创建 Graph 类型的图表,就创建了一个空的图表,如下所示:
单击当前的图表,选择 Edit,修改如下几个地方:
效果如下所示:
middlewares/statsd.js
const StatsD = require('node-statsd') const statsdClient = new StatsD({ host: 'localhost', port: 8125 }) module.exports = function (routerName) { return async function statsdMiddleware (ctx, next) { const start = Date.now() try { await next() const spent = Date.now() - start statsdClient.timing(`api_${routerName}`, spent) } catch (e) { statsdClient.increment(`api_${routerName}_${e.status || (ctx.status !== 404 ? ctx.status : 500)}`) throw e } } }
server.js
const Bluebird = require('bluebird') const Paloma = require('paloma') const app = new Paloma() const statsd = require('./middlewares/statsd') app.route({ method: 'GET', path: '/', controller: [ statsd('getHome'), async (ctx) => { // 模拟十分之一出错概率 if (Math.random() < 0.1) { console.error('error') ctx.throw(400) } // 模拟 1-100 毫秒响应时间 const responseTime = Math.floor(Math.random() * 100 + 1) await Bluebird.delay(responseTime) console.log(`Spent ${responseTime}ms`) ctx.status = 200 } ]}) app.listen(3000)
client.js
const axios = require('axios') setInterval(() => { // 模拟 1-10 的 tps const tps = Math.floor(Math.random() * 10 + 1) for (let i = 0; i < tps; i++) { axios.get('http://localhost:3000') } }, 1000)
打开两个终端,分别运行:
$ node server.js $ node client.js
回到 influxdb-admin,输入:
可以看到已经有 api_getHome 和 api_getHome_400 表了。回到 Grafana,在一行(row)里创建两个图表,分别为:
以 “getHome 响应时间” 的图表为例,Metrics 配置截图如下:
上一节:6.5 Sentry
下一节:7.2 Telegraf + InfluxDB + Grafana(下)
Copyright© 2013-2020
All Rights Reserved 京ICP备2023019179号-8