Back
Featured image of post 监控方案-druid篇

监控方案-druid篇

监控系统-druid.io

公司的业务日志是通过syslog-ng喂给kafka,提供给spark消费并进行数据清洗,然后把数据导入到druid进行实时聚合查询。
监控维度覆盖到了druid.io的性能指标上,而针对druid.io的监控能找到的文档不多,官方文档略显简陋而且分散,方案落地的时候碰到了很多坑。
趁记忆还新鲜整理出这篇文章。

部署及配置

方案说明

druid配置graphite-emitter,把相关metrics发送给graphite,然后由grafana做前端展示及告警

版本说明

系统版本:Ubuntu 14.04
druid版本:imply-2.5.5 druid-0.12.0
graphite版本: latest

druid配置

关于监控,druid有几个相关术语简单解释下。

  • metrics
  • monitors
  • emitter

metrics

druid提供的用于监控的各类指标,包括各节点的系统资源使用统计,请求相关统计等。
格式默认是json。通用字段包括 timestamp,metrics,service,host,value。
不过有一些metrics会有额外的dimensions,比如dataSource,type等。

monitors

同一类别metrics分属的组。
druid支持的monitors包括(由于公司架构不包含realtime等节点,这里仅列举我使用的monitors):

  • io.druid.client.cache.CacheMonitor
    Historical和Broker两个节点的cache统计数据
  • com.metamx.metrics.SysMonitor
    系统资源使用量统计,这里记得需要下载一个jar包在lib目录
  • io.druid.server.metrics.HistoricalMetricsMonitor
    Historical节点数据统计
  • com.metamx.metrics.JvmMonitor
    JVM相关统计
  • io.druid.server.metrics.QueryCountStatsMonitor
    Broker,historical两个节点的请求数统计

emitter

发送metrics的工具。 默认是logging,即直接把监控数据写入日志中。后续脚本筛选出来发送给监控系统,扩展性太差。
还有一种方式’http',把metrics通过POST的方式发送给server。 两者可以混合使用,不过日志量实在太大…除此之外,还有一种选择,就是graphite emitter。
优点当然是配置灵活,扩展性强。 不过graphite-emitter是社区版的一个插件,需要独立安装。

这里需要重点注意的是:

不同的metrics归属于不同的monitors,而不同的节点支持的monitors不同

所以monitors配置尽量不要配置在common下,以免出现报错,甚至出现druid节点无法启动的现象。
比如监控historical的统计数据,就需要开启io.druid.server.metrics.HistoricalMetricsMonitor,如果配置在common中,你会发现其他节点有各种诡异的报错,各种启动失败…跳坑无数的血泪教训

部署过程

安装graphite

关于graphite,只需要了解大概架构即可。其实有点类似ELK的模式,graphite也包括三种模块。

  • carbon: 接收数据。本身并不会采集数据。这一点官方文档特意强调了。
  • whisper: 时序数据库,存储carbon接收的数据。替代品包括influxdb等。
  • graphite-web: Django编写的一个web应用,把数据渲染成图形。替代品当然是美丽优雅的grafana了。

如上所述,其实graphite本身也有绘图功能,只不过效果相当简陋…还好grafana有官方app可以直接使用graphite当作data source。
尝试了一次graphite的部署过程,实在痛苦不堪。模块多,python及pip多版本的兼容性是个很大的坑,依赖库django的兼容性更是坑上加坑。我花了一天的时间调试才勉强搭建好测试环境。

此后线上环境为了节省时间,我直接上了docker。

sudo apt-get update
sudo apt-get install \
    linux-image-extra-$(uname -r) \
    linux-image-extra-virtual
sudo apt-get install \
    apt-transport-https \
    ca-certificates \
    curl \
    software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo add-apt-repository \
   "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
   $(lsb_release -cs) \
   stable"
sudo apt-get update
sudo apt-get install docker-ce

国内docker pull也是蜜汁缓慢,为此我还得配置一个加速器

sudo vim /etc/default/docker 
    DOCKER_OPTS="--registry-mirror=https://registry.docker-cn.com"
sudo service docker restart

终于可以愉快运行了

sudo docker run -d --name graphite --restart=always -p 80:80 -p 2003-2004:2003-2004 -p 2023-2024:2023-2024 -p 8125:8125/udp -p 8126:8126 graphiteapp/graphite-statsd

此处端口可以看到一共开放了7个端口,其中,80端口是前端web页面。
carbon支持两种协议的接收方式,一种是The plaintext protocol,端口为2003,另一种是The pickle protocol,端口为2004。
而2023和2024分别对应两个接收方式的聚合器carbon-aggregator.py的端口。
8125和8126是statsd对应的端口,此处用不到。

此处需要注意的一点是,nc和telnet等命令使用的是The plaintext protocol协议,也就是2003端口。而druid的graphite-emitter使用的是The pickle protocal,即2004端口。

测试数据

PORT=2003
SERVER=graphite.your.org
echo "local.random.diceroll 4 `date +%s`" | nc -c ${SERVER} ${PORT}

访问http://127.0.0.1可以看到略显丑陋的界面。

druid-graphiter插件部署

druid插件包括core和community两种,前者集成在druid里面,无需额外按照,后者需要根据匹配的版本号去自行安装。
安装包命名格式如下:

                                       名字 :版本号
io.druid.extensions.contrib:graphite-emitter:0.12.0

安装graphite-emitter extensions

cd $Druid_PATH/

java \
  -cp "lib/*" \
  -Ddruid.extensions.directory="extensions" \
  -Ddruid.extensions.hadoopDependenciesDir="hadoop-dependencies" \
  io.druid.cli.Main tools pull-deps \
  --no-default-hadoop \
  -c "io.druid.extensions.contrib:graphite-emitter:0.12.0"

配置include Emitter

vim common.runtime.properties
    druid.extensions.loadList=[...,"graphite-emitter"] #最后面加入graphite-emitter即可

配置Monitoring

此处记得大坑,不同的monitors一定要针对性配置在对应的模块下,不要全部写入common。

vim common.runtime.properties
  druid.monitoring.monitors=["com.metamx.metrics.SysMonitor","com.metamx.metrics.JvmMonitor"]
  druid.emitter=graphite 
  druid.emitter.graphite.hostname=127.0.0.1
  druid.emitter.graphite.port=2004   #记得上文解释的两种协议吧。这里配置pickle协议的2004端口
  druid.emitter.graphite.eventConverter={"type":"whiteList", "namespacePrefix": "druid.SYS_JVM", "ignoreHostname":true, "ignoreServiceName":false, "mapPath":"conf/druid_metric_whitelist.j
son"}
  druid.emitter.logging.logLevel=info
  druid.monitoring.emissionPeriod=PT1m   #自定义设置采集周期。默认1min
vim broker/runtime.properties
  #monitor
  druid.monitoring.monitors=["io.druid.client.cache.CacheMonitor","io.druid.server.metrics.QueryCountStatsMonitor"]
  druid.emitter=graphite
  druid.emitter.graphite.hostname=127.0.0.1
  druid.emitter.graphite.port=2004
  druid.emitter.graphite.eventConverter={"type":"whiteList", "namespacePrefix": "druid.broker", "ignoreHostname":true, "ignoreServiceName":false, "mapPath":"conf/druid_metric_whitelist.js
on"}
  druid.emitter.logging.logLevel=info
  druid.monitoring.emissionPeriod=PT1m
vim historical/runtime.properties
  #monitor
  druid.monitoring.monitors=["io.druid.server.metrics.HistoricalMetricsMonitor","io.druid.client.cache.CacheMonitor","io.druid.server.metrics.QueryCountStatsMonitor"]
  druid.emitter=graphite
  druid.emitter.graphite.hostname=127.0.0.1
  druid.emitter.graphite.port=2004
  druid.emitter.graphite.eventConverter={"type":"whiteList", "namespacePrefix": "druid.historical", "ignoreHostname":true, "ignoreServiceName":false, "mapPath":"conf/druid_metric_whitelis
t.json"}
  druid.emitter.logging.logLevel=info
  druid.monitoring.emissionPeriod=PT1m

关于all 和白名单模式

all会接收到很多无用的信息。白名单模式只需配置自己监控的metrics即可。
关于白名单json文件,根据官方文档关于metrics的接收按需配置,格式请参考https://github.com/druid-io/druid/blob/master/extensions-contrib/graphite-emitter/src/main/resources/defaultWhiteListMap.json

conf/druid_metric_whitelist.json

{
  "query/time": [
    "dataSource",
    "type"
  ],
  "query/node/time": [
    "dataSource",
    "type"
  ],
  "query/success/count": [],
  "query/failed/count": [],
  "query/interrupted/count": [],
  "query/segment/time": [
    "dataSource",
    "type"
  ],
  "query/cache/delta": [],
  "query/cache/total": [],
  "segment/max": [],
  "segment/used": [],
  "segment/usedPercent": [],
  "segment/count": [],
  "jvm/gc": ["gcName"],
  "jvm/mem": ["memKind"],
  "jvm/pool": ["poolKind","poolName"],
  "sys/net":[],
  "sys/fs":[],
  "sys/mem":[],
  "sys/cpu":[]
}

namespacePrefix此时可以根据节点分别命名为

druid.broker
druid.historical
...

这样graphite查询结构就可以节点分开了

文档参考

关于监控metrics的说明 http://druid.io/docs/0.12.0/operations/metrics.html

关于monitors及metrics配置相关的说明 http://druid.io/docs/latest/configuration/index.html

关于graphite-emitter配置相关的说明 http://druid.io/docs/0.12.0/development/extensions-contrib/graphite.html

Built with Hugo
Theme Stack designed by Jimmy