监控

influxdb 排坑记

相同点覆盖

Duplicate points

A point is uniquely identified by the measurement name, tag set, and timestamp. If you submit Line Protocol with the same measurement, tag set, and timestamp, but with a different field set, the field set becomes the union of the old field set and the new field set, where any conflicts favor the new field set.

相同的 measurement,tagset 和 timestamp 的数据会覆盖

解决方法:

  1. 提高时间精度
  2. 增加一个tag来标识不同的点
  3. 预处理数据 ✔️

每个点的 tag 数量

opentsdb 限制为每个点 8 个 tag

influxdb 限制不明确,最好也不要太多

在设计数据库是需要考虑的是,同一类型的字段作为 tag key 还是 tag value?

两种情况分别为:

time        key1 key2 key3
1500000000  true true true
1500000001  true false false
time        key   value
1500000000  _key1 true
1500000000  _key2 true
1500000000  _key3 true
1500000001  _key1 true
1500000001  _key2 false
1500000001  _key3 false

假设某个类型的字段可选值为 k 个,而一个用有 n 个这样的字段。如果作为 tag key,那么可能数据库的 series 复杂度是 O(k^n)。而作为 tag value,那么数据库的复杂度是 O(k * n)。也就是第二种的 series 复杂度大大降低。

但是对于第二种方法,效果就是打的点更多。第一种方法打点 m 个的时候,第二种需要 m * n 个。

另外考虑对于 down sampling 的友好性,虽然第二种造成点更多,但是在进行 down sampling 的时候有更好的压缩效率。

https://docs.influxdata.com/influxdb/v1.2/concepts/schema_and_data_layout/#don-t-have-too-many-series

max-values-per-tag 限制

每个 tag 可选值也有限制,不能超过10万,tag用于标识点,而不是用于存储数据,如果需要存储数据,应该使用 fields。

比如:

  • 域名:可选范围很大
  • 邮箱:可选范围几乎无限大
  • UUID

max-series-per-database 限制

tagset 的定义:每一个点的 tag key 和 tag value 的组合
series 的定义:使用同一个 measurement,retention policy,tagset 组合的点的集合

每一个数据库中的 series 的数量不能超过 100 万

以上连个限制的原因在于,influxdb 为每个 series 建立了索引并且常驻内存,如果过大

tag 只能存储字符串

一般来说,在 tag 中应该存储的是 enum 的值,而不是任意的字符串。

推荐配置

https://docs.influxdata.com/influxdb/v1.6/concepts/schema_and_data_layout/

如果想要使用 group by,推荐使用 tags
如果需要使用函数(mean,sum), 只有 fields 才能
如果需要使用数字,只有 fields 才能

硬件配置

https://docs.influxdata.com/influxdb/v1.6/guides/hardware_sizing/

Python + Influxdb + Grafana 的监控系统

# influxdb

为什么我们要把监控数据存到 influxdb 呢? 存到 MySQL 或者 MongoDB 甚至 Elasticsearch 不好么?

数据模型上, 监控数据是和时间相关的, 脱离点产生的时间, 那么数据将毫无意义, 传统数据库中并没又强调这一点.

性能上, influxdb 是时间序列数据库, 这类数据库面临的问题是写入非常多, 而读取比较少. 而普通的数据库一般都是读比较多, 而写入较少, 并且要保证写入的正确性.

监控打点显然是一个面向时间序列的过程, 并且写入非常多, 而一般只有在触发告警, 排查问题的时候可能读取才比较多. 所以从性能和功能考虑上来说, 传统数据库都是不适用的.

influxdb 中常见的存储数据格式:

“`
cpu_usage value=49 1502043216
cpu_usage value=50 1502193042
cpu_usage value=5 1502196258
“`

## influxdb 数据模型

我们以一个 measurement(测量) 作为一个表, tag-value, field-value 都是记录数据的键值对, 区别是 tag 是由索引的, 而 field 没有, timestamp 是时间戳. tag set 自然指的是一组 tag 的组合.

“`
measurement,tag=value,tag1=value1 field=value,field1=value1 timestamp
“`

`measurement + tag set` 被称为一个序列(series). 每一个 series 都可以指定不同的 retention policy.

## influxdb 查询

使用类似 SQL 的语言, 执行 `influx` 进入shell

“`
> CREATE DATABASE mydb
> SHOW DATABASES
> USE mydb
“`
插入数据, 和 SQL 差别还是挺大的, 其中 cpu 是 measurement, 也就是 “表名”, 没指定时间的话, influxdb 会自己加上.

“`
INSERT cpu,host=serverA,region=us_west value=0.64
“`

查询数据, 注意多出来的 timestamp 一栏

“`
> SELECT “host”, “region”, “value” FROM “cpu”
name: cpu
———
time host region value
2015-10-21T19:28:07.580664347Z serverA us_west 0.64
“`

## 回收策略

默认情况下, influxdb 会永久保留数据, 一般来说这样是没有意义的, 我们可以设置短一点.

“`
CREATE RETENTION POLICY ON DURATION REPLICATION [DEFAULT]
“`

其中 replication 只能设置为 1, 因为开源版只有 1. 可以设置成 30d, 1w

# Python 客户端的编写

看到这里有人可能要问了, 不是有 python-influxdb 这个库么, 好好地客户端你为什么要封装一层呢? 答案很简单: 性能.

1. 调用 `influxdb.write_points()` 是一个涉及到网络的阻塞操作, 极有可能对于程序造成性能影响.
2. 如果我们在程序中散落着各种打点的代码, 那么就会造成没打一个点都去调用一些 IO, 不如放在一个队列里面可以每次多打几个, 减少 IO 次数, 这样对程序和 influxdb 的性能都有好处.

## UDP vs http

influxdb 支持使用 UDP 和 HTTP 两种协议访问. 显然对于打点这种操纵来说, 我们不关心响应结果, 哪怕一个点没打上, 没打上就没打上吧……所以采用 UDP 就好了. 根据测试 udp 的性能在 http 的几十倍.

按照 influxdb 官网的建议, 我们需要调整 UDP buffer 的 size 到 25MB(26214400B) 为宜.

查看系统的 udp buffer 大小:

“`
$ sysctl net.core.rmem_max
$ sysctl net.core.rmem_default
“`

修改 `/etc/sysctl.conf` 文件:

“`
net.core.rmem_max=26214400
net.core.rmem_default=26214400
“`

但是这个设置只有到下次重启才能生效, 继续使用 sysctl 设置立即生效:

“`
$ sysctl -w net.core.rmem_max=26214400
$ sysctl -w net.core.rmem_default=26214400
“`

另外注意, UDP 有一个大坑, 只吃吃精度为 s 的打点, 所以在配置和客户端中都必须使用这个时间精度.

P.S. 中文互联网上的好多教程都在使用 http 打点, 误人子弟, 毁人不倦啊……

参考:

1. https://docs.influxdata.com/influxdb/v1.6/supported_protocols/udp/
2. https://github.com/MikaelGRA/InfluxDB.Client/issues/31
3. https://blog.codeship.com/a-deep-dive-into-influxdb/
4. http://docs.grafana.org/features/datasources/influxdb/

influxdb+grafana+telegraf 监控系统搭建

本文基于 ubuntu 18.04

# 要不要用 docker?

这是一个哲学问题,用不用其实都有各自的好处。不过在这里我倾向于不用。因为 influxdb
和 grafana 都有好多的状态,而且不是都可以写到 mysql 中的,所以既然还得 mount 出来,
何苦用 docker 呢?telegraf 需要采集系统的相关信息,更不适合放在 docker 里面。

– InfluxDB,开源的时间序列数据库
– Grafana,开源的数据可视化工具

# 搭建过程

## influxdb && telegraf

因为这两个都是一家的产品,所以安装步骤都是一样的。按照[官网](https://docs.influxdata.com/influxdb/v1.6/introduction/installation/)给的安装步骤,其实很简单的。

“`
curl -sL https://repos.influxdata.com/influxdb.key | sudo apt-key add –
source /etc/lsb-release
echo “deb https://repos.influxdata.com/${DISTRIB_ID,,} ${DISTRIB_CODENAME} stable” | sudo tee /etc/apt/sources.list.d/influxdb.list

sudo apt-get update && sudo apt-get install influxdb telegraf
sudo systemctl start influxdb telegraf
“`

我们暂时就不配置了,直接使用默认配置。可以通过 `systemctl status influxdb` 来查看状态

## grafana

同样参考[官网](http://docs.grafana.org/installation/debian/)的教程。

## 基本概念

Grafana 从数据源中读取数据, 数据源一般是时间序列数据库. their data can be mixed in a single panel.

Grafana 使用 `orginazations` and `users` to manage permissions.

A dashboard consists of rows, rows consist of panels. for each panel, there is a query editor to edit which data the panel should show.

# 参考

1. http://docs.grafana.org/guides/gettingstarted/
2. http://docs.grafana.org/guides/basic_concepts/

“`
VERSION=5.1.4
wget https://s3-us-west-2.amazonaws.com/grafana-releases/release/grafana_${VERSION}_amd64.deb
apt-get install -y adduser libfontconfig
dpkg -i grafana_${VERSION}_amd64.deb

sudo /bin/systemctl daemon-reload
sudo /bin/systemctl enable grafana-server
sudo /bin/systemctl start grafana-server
“`

然后就 ok 啦,打开 http://ip:3000 就能访问 grafana 的界面了,默认用户名和密码是 admin。如果是在阿里云等云上面,注意要在安全组里面开一下 3000 端口。

# 配置

## 配置 telegraf 的插件

## 配置 grafana 的 datasource

未完待续

# 参考资料

1. https://blog.csdn.net/w958660278/article/details/80484486
2. https://juejin.im/post/5b4568c851882519790c72f3
3. https://grafana.com/dashboards/928

监控系统基本概念与选型

# 时序数据库

监控系统的基础是时序数据库

现代的监控系统一般都有如下几部分组成:

时序数据库 + 前端显示 + 报警系统 + 指标收集

一般需要实现的功能:

– 度量数据收集和可视化
– 收集尽可能多的性能和状态数据
– 图形化做有意义的展示
– 如果发现可疑问题,可以关联其他图表找到原因
– 错误检测
– 按需告警, 触发条件越宽松则告警应该越少
– 避免误报

从监控的层次划分的话,一般包含三层监控:

– 基础层: 主机的CPU,内存,网络及IO等
– 中间层: 应用运行的中间件层, Nginx, Tomcat, MySQL, Redis
– 应用层: 服务端及客户端性能数据,如API访问次数和响应时间等

现代的监控越来越关注应用层和其他层数据的整合能力, 具有快速找到系统瓶颈, 方便扩容或代码优化.

# 时序数据库的选择

监控数据往往都带有时间戳,其实就是一种典型时间序列数据,而这方面已经有很多专门的存储系统,如 opentsdb,influxdb,prometheus 等。相比 mysql 这样的传统数据库,这类系统在存储、查询上针对时间序列数据都做了特别的优化。

其中 opentsdb 基于 hadoop 生态系统,考虑到搭建的复杂度,暂时不考虑了。influxdb 和 prometheus 都是 Golang 编写的,直接一个二进制文件就可以运行。两者的区别有:

– prometheus 对于保存长时间的数据有一些问题,influxdb 似乎没有问题
– 另外 influxdb 可以直接写入,而 prometheus 是基于拉(pull)模式的,也就是说程序不能直接写入 prometheus,而是需要由 prometheus 去定期拉监控数据,太反人类了。
– influxdb 的查询类似 SQL,而 prometheus 的查询语法更加简洁,但是有学习成本,各有千秋吧

所以选用 influxdb了。

# 前端显示

唯一的标准自然是越漂亮越好,所以我们选择 grafana。

当然另一需要考虑的是编写查询界面不要过于复杂,这方面 grafana 只需要拖拽空间和勾勾选选就可以了,显然不成问题。

# 报警系统

grafan 自带了一些报警,但是只能根据阈值报警,显然不能满足我们的需求。我们这里选择了 bosun,是 Stack Overflow 开源的一款监控系统。通过简单的几个语句就可以编写复杂的报警条件。

# 指标收集

按照前面的分析,对于应用层,也就是我们自己的代码,可以随意地添加代码打点,这里不再赘述。对于系统的 metrics 的收集,可以使用 influxdb 公司钦定的 telegraf。telegraf 也有一些不同的插件,可以很好地支持 mysql、redis 等的监控数据收集。

# 参考

1. [Logs and Metrics and Graphs, Oh my!](https://grafana.com/blog/2016/01/05/logs-and-metrics-and-graphs-oh-my/)
2. [Prometheus 和 influxdb 对比](https://www.gaott.info/prometheus-vs-influxdb/)
3. [360基于Prometheus的在线服务监控实践](https://dbaplus.cn/news-72-1462-1.html)
4. [虎牙直播运维负责人张观石:基于时序数据库的直播业务监控实践](http://www.yunweipai.com/archives/20983.html)
5. [监控系统选型](http://xoyo.space/2017/04/new-monitor-architecture/)
6. [openTSDB/Bosun报警语法 介绍/学习笔记](https://blog.csdn.net/lslxdx/article/details/79454916)