使用 StatsD、Graphite 等搭建 Web 监控
除了对应用程序的异常做监控,我们还需要对服务器的硬件、流量和应用相关服务运行情况做监控、搜集数据和绘制图表。通过搜集到的数据,我们可以发现当前系统的瓶颈,作为故障排除依据,决策何时扩展以及如何扩展等。
常见的运维监控工具及其主要应用场景如下。
- Zabbix:诞生于 1998 年的企业级分布式监控系统,可以自动发现、自动注册服务器、实时绘图、存储历史数据。
- Nagios:通过安装插件和编写监控脚本可以很容易地实现绝大部分的定制需求,它轻量灵活,且报警机制很强,但是在监控的服务器数量较多时会有性能瓶颈。Nagios 在绘制图表方面很弱,常使用 Cacti 补充。Cacti 是使用 PHP 语言开发的网络流量监测图形分析工具,用 RRDTool 存储和更新数据,当用户需要查看数据的时候用 RRDTool 生成图表呈现给用户。
- Icinga:最初是 Nagios 的一个分支,1.x 版本和 Nagios 功能基本一样,只是添加了 Icinga-Web 的 REST API 等。
- Icinga2:在 Icinga2(2.x)版本下重写了 Icinga,它默认就支持 Graphite,使用多线程来提高运行效率(官网称 1 分钟百万级别地动态检查监控 6 万台主机没有卡顿),使用全新的 Icinga-Web 2,还支持可拖放的定制仪表盘。
对于服务器的硬件、流量和应用相关服务运行情况的监控和报警,推荐使用 Icinga2。而绘制图表,则选择更流行的 StatsD+Graphite+Grafana+Diamond 组合。
- Graphite:一个基于 Django 的企业级监控工具,能实时可视化和按时间序列存储数据。严格地说,Graphite 只是一个根据数据实时绘图的工具,数据收集通常由第三方工具(如 Ganglia、Collectd、StatsD、Diamond、Bucky 等)或插件完成,还可根据其协议选用别的数据源供其绘图。我们这里只使用它做数据库存储。
- StatsD:它是一个 NodeJS 的 Daemon 程序,最初由 Flickr 实现,Etsy 将其重构。StatsD 运行在每台服务器上,服务器上的程序发送各种关键指标到本地 StatsD 进程,最后 Graphite 根据 StatsD 聚合的数据画图。
- Diamond:一个 Python 的指标收集守护程序,它自带了 CPU、内存、网络、系统负载、磁盘等方面的指标收集器,也非常容易地实现自定义的收集器。
- Grafana:一个开源、功能强大、可定制性高的指标仪表板和图形编辑器工具。不直接使用 Graphite 展示图表,是因为它的界面和功能过于简单、页面样式比较陈旧。使用 Grafana 来汇集 Graphite 的测量数据,并以图形方式显示是个很好的选择。
Graphite 包含如下三个组件。
- Carbon:基于 Twisted 的进程,接收时间序列数据。Twisted 框架让它能够以很低的开销处理大量的客户端和流量。
- Whisper:专门存储时间序列类型数据的小型数据库。
- Graphite-web:一个基于 Django 的可以高度扩展的实时画图系统,还提供查询数据的 API。
安装 Graphite 的步骤如下:
> sudo mkdir /opt > sudo chown ubuntu:ubuntu /opt-R > sudo apt-get install libcairo2-dev > git clone git://git.cairographics.org/git/py2cairo > ./autogen.sh && make && sudo make install > pip install carbon --install-option="--prefix=/opt/graphite" --install-option="-- install-lib=/opt/graphite/lib" > pip install graphite-web --install-option="--prefix=/opt/graphite" --install-option ="--install-lib=/opt/graphite/webapp" > pip install cairocffi whisper django==1.8.11 # 目前 Graphite 对 1.9 支持有限,先使用 1 .8 的最高版本
配置 Graphite
> cd /opt/graphite/webapp/graphite > cp local_settings.py.example local_settings.py > cd /opt/graphite/conf/ > cp carbon.conf.example carbon.conf > cp storage-schemas.conf.example storage-schemas.conf > cp graphite.wsgi.example ../webapp/graphite/graphite_wsgi.py
其中 storage-schemas.conf 在中间添加一项 statsd:
> cat storage-schemas.conf [carbon] pattern=^carbon\. # 匹配以 carbon 字符串开头的指标项名称 retentions=60:90d # 数据点每 60 秒记录一次,并保存 90 天 [statsd] pattern=^stats.* # 匹配以 stats 字符串开头的指标项名称 retentions=10s:1d,1m:7d,10m:1y # 数据点每 10 秒记录一次,并保存 1 天;数据点每 1 分钟 记录一次,并保存 7 天;数据点每 10 分钟记录一次,并保存 1 年 [default_1min_for_1day] pattern=.* # 捕捉与 Carbon 和 Statsd 无关的全部指标项 retentions=60s:1d # 数据点每 60 秒记录一次,并保存 1 天
默认 Graphite 使用 SQLite 存储数据库,我们换成 MySQL,使用之前的数据库 r。修改 local_settings.py 的 DATABASES 的设置:
DATABASES={ 'default':{ 'NAME':'r', 'ENGINE':'django.db.backends.mysql', 'USER':'web', 'PASSWORD':'web', 'HOST':'localhost', 'PORT':'' } }
生成 Graphite 需要的表结构:
> python manage.py syncdb > python manage.py migrate
使用 createsuperuser 创建一个超级管理员,未来使用它登录 Graphite-Web:
> python manage.py createsuperuser
Carbon 包含 3 个守护进程。
- carbon-cache.py:接收指标项数据,并用底层的 Whisper 库按照指定的时间间隔将这些值写入磁盘。
- carbon-relay.py:用来复制和分片。
- carbon-aggregator.py:运行于 carbon-cache.py 前面,在 Whisper 中记录指标项之前,将这些指标项缓存一段时间。通常用在不需要细粒度报告的场景下。
本节仅展示单机的简单模式,因此只需要启动 carbon-cache.py 进程:
> cd /opt/graphite/ > ./bin/carbon-cache.py start
启动 Graphite-Web:
> cd /opt/graphite/webapp/graphite > gunicorn graphite_wsgi:application -b 0.0.0.0:9000
在实际生产环境中,应该使用之前介绍的 Nginx+Gunicorn 或者 Nginx+uWSGI 的组合。
使用 StatsD
> sudo apt-get install nodejs-y # 需要先安装 Node.js > cd /opt > git clone git://github.com/etsy/statsd.git > cd statsd > cp exampleConfig.js Config.js
Config.js 改成:
{ graphitePort:2003, graphiteHost:"localhost", port:8125, backends:["./backends/graphite"] }
启动 StatsD:
> nodejs stats.js Config.js
配置 Diamond
> pip install diamond --install-option="--prefix=/opt/diamond" > cd /opt/diamond/etc/diamond > cp diamond.conf.example diamond.conf > mkdir /opt/diamond/run > sudo mkdir /var/log/diamond > sudo chown ubuntu:ubuntu /var/log/diamond -R
需要修改 diamond.conf 的如下配置:
[server] handlers=diamond.handler.stats_d.StatsdHandler pid_file=/opt/diamond/run/diamond.pid collectors_path=/opt/diamond/share/diamond/collectors/ collectors_config_path=/opt/diamond/etc/diamond/collectors/ handlers_config_path=/opt/diamond/etc/diamond/handlers/ handlers_path=/opt/diamond/share/diamond/handlers/
发布指标项
指标项(metric)是一种随着时间不断变化的可度量的值。例如内存占用情况、每秒请求数、请求处理时间等。发给 Carbon 的数据包含如下三种信息:
- 指标项名称。
- 度量值。
- 时间序列,通常是时间戳。
可以通过如下命令把指标直接发送到 Carbon 上:
> echo "carbon.agents.web.metricsReceived 28198 `date+%s`"|nc localhost 2003
而发送给 StatsD 的格式则有些变化:
> echo "sampling:1|c|@0.1" | nc-u-w0 127.0.0.1 8125
type_specification 用来聚合类型,不需要添加时间戳字段。StatsD 提供了额外的聚合指标功能,每次在设置的 flushInterval 的时间(默认是 10 s)超时后聚合,然后发送给 Carbon 或者其他后端服务。
1.Counting:使用 c 表示,也就是一个 sum 操作。
> echo "counter:1|c" | nc-u-w0 127.0.0.1 8125
2.Sampling:取样。下例表示取 1/10 的结果。
> echo "sampling:1|@0.1" | nc-u-w0 127.0.0.1 8125
3.Timing:定时收集。下例表示收集 1 s 内的指标,再取 1/10 的结果。
> echo "timing:1000|ms|@0.1" | nc-u-w0 127.0.0.1 8125
生成的指标包含 mean、sum、count、min、max 等几种类型,后面还可以使用百分比(默认是 90,也就是 90%)。下面用代码展示它们的含义:
In : dataset=[9, 89, 44, 97, 80, 62, 63, 22, 81, 27] # 一个无序的数据集 In : sorted_dataset=sorted(dataset) # 先排序 In : percentile=90 In : percentile_90=sorted_dataset[:int(len(sorted_dataset)*percentile / 100)] # 获 得最好的 90%的指标 In : percentile_90 Out: [9, 22, 27, 44, 62, 63, 80, 81] In : lower_90=min(percentile_90) # 最小值 9。lower 和 lower_90 其实是一个意思 In : mean_90=mean(percentile_90) # 平均值 48.5 In : upper_90=max(percentile_90) # 最大值 90 In : sum_90=sum(percentile_90) # 总数 388
1.Gauges:如果发送的指标没有更新,就会一直发送这个值,还可以通过相对的计算来更新而不是直接设置为其他值。
> echo "gauges:1000|g" |nc -u -w0 127.0.0.1 8125 > echo "gauges:-20|g" |nc -u -w0 127.0.0.1 8125 # 发送 980 > echo "gauges:+10|g" |nc -u -w0 127.0.0.1 8125 # 发送 990
2.Sets:只记录去重的集合。已经存在的指标值不会被发送,下例只会发送两个指标。
> echo "sets:20|s" |nc -u -w0 127.0.0.1 8125 > echo "sets:20|s" |nc -u -w0 127.0.0.1 8125 > echo "sets:19|s" |nc -u -w0 127.0.0.1 8125
3.多指标:我们可以把上述 5 种指标组合,使用\n 分隔:
> echo "counter:1|c\ntiming:320|ms\ngauges:-20|g\nuniques:111|s" | nc -u -w0 127.0.0.1 8125
使用 Grafana
登录 graphite-Web 就可以看到我们发送的这些指标了,如图 7.7 所示。
图 7.7 发送的指标
其中 Diamond 产生的指标都放在 Metrics->stats->gauges->servers 下。页面比较粗糙,现在使用 Grafana 来代替:
> sudo apt-get install -y adduser libfontconfig > cd /tmp > wget https://grafanarel.s3.amazonaws.com/builds/grafana_2.6.0_amd64.deb # 使用 apt 安 装很慢,换成 deb 包的方式安装 > sudo dpkg -i grafana_2.6.0_amd64.deb
修改/etc/grafana/grafana.ini 中如下的设置:
[database] # Either"mysql","postgres"or"sqlite3", it's your choice type=mysql host=127.0.0.1:3306 name=r user=web password=web [server] http_port=5000 [security] admin_user=dongwm admin_password=123
启动服务:
> sudo /etc/init.d/grafana-server start
访问 http://localhost:5000,用户名 dongwm,密码为 123。先创建数据源。访问 http://localhost:5000/datasources/new。填好类似的如图 7.8 所示表单。
图 7.8 表单
单击右下角的“Add”,提示添加成功。
然后创建绘图面板。打开首页 http://localhost:5000,打开如图 7.9 所示的 Home 下拉框。
图 7.9 打开 Home 下拉框
单击最下面的“New”按钮。也可看到页面中间靠上的位置有一个绿色的小长块,打开它,选择 Add Panel->Graph,如图 7.10 所示。
图 7.10 选择 Add Panel->Graph
然后就进入了面板创建页。一个面板可以添加多个指标。我们添加 Diamond 创建的几个指标,如图 7.11 所示。
图 7.11 添加 Diamond 创建的几个指标
Query A 使用星号“*”匹配的全部类型,Query B 是为了演示而添加的。可以单击+Query 按钮添加更多的 Query。
面板的标题等内容可以通过编辑原始 JSON 元数据来设置。
这样一个面板就做好了,如图 7.12 所示。
图 7.12 做好的面板
可以通过单击“ADD ROW”添加更多的面板。
使用 Kenshin
Kenshin(https://github.com/douban/Kenshin )是豆瓣开源的时间序列数据库,它可用来替代 Whisper,IOPS(Input/Output Operations Per Second,即每秒进行读写〈I/O〉操作的次数)提高了 40 倍。
还可以使用 carbon-c-relay 替代 carbon-relay,让 CPU 使用率降为原来的 10%。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论