加入新公司后不久开始怀念xflush,大部分情况下只需在页面上配置, 就可以实现业务指标的可视化及异常报警。
尝试利用现有的开源系统搭建,经过调研分析,最终确定的方案为statsd+influxdb+grafana。目前已上线,运行稳定。
具体过程不再细说,其中重要的取舍和配置介绍如下。
老牌的企业级的监控工具。
环境搭建繁琐: 参考官方文档和网上各种文档,踩各种坑,加上工作上有其它事情在忙,搭建花了2-3天之久。
性能: graphite的存储组件whisper 是零散小文件存储,这样写指标文件会造成随机io。性能不敢恭维。
界面: 比较传统的树形结构,略显土气。进一步调研时发现了grafana。
对数据时间范围内汇总,大大减少了db的压力。并能进行min, max, avg多维度统计。
使用 Go 语言编写,无需外部依赖。反之OpenTSDB 是一种基于 HBase 的时间序列数据库。
最新版本的存储引擎底层是B+树, 也支持批量写入和缓存。
InfluxDB内部集成支持 graphite数据格式。 每次统计指标的min, max, avg对应到数据库中是一条记录的多个列, 相比graphite降低了不必要的io开销。
界面相当漂亮,功能齐全的度量仪表盘和图形编辑器和查询编辑器。
当时使用了kapacitor。 目前grafana4.0 已经release, 直接支持alerting。
业务指标的主要内容: qps/qpm, 延迟。
对java-statsd-client进行了封装,使用注解和aop xml配置进行业务指标汇报,业务代码无侵入。
java-statsd-client 内部使用udp发送指标统计到StatsD,没有复杂的状态管理。对业务影响很小。另外一种方案就是记录到日志,flume收集后再发送到StatsD,彻底隔离对业务的影响。
StatsD为无状态节点,可通过负载均衡器部署多台保证可靠性和可伸缩性。
InfluxDB存储到达瓶颈后,可以做分库的方案,增加一个代理层。StatsD和Grafana通过代理层访问InfluxDB。
sudo yum install epel
sudo yum install nodejs
cd /opt/
sudo git clone git://github.com/etsy/statsd.git
sudo cp exampleConfig.js Config.js
sudo vim Config.js
{
graphitePort: 2003
, graphiteHost: "x.x.x.x"
, port: 8125
, flushInterval: 60000
,backends: [ "./backends/graphite", "./backends/console" ]
,debug: true
}
statsD默认为qps统计,如修改为qpm, 修改lib/process_metrics.js
current_timer_data["count_ps"] 修改为 current_timer_data["count_ps"] = timer_counters[key];
counter_rates[key] 修改为 counter_rates[key] = value ;
可直接运行 node stats.js config.js
另外node-forever 提供了守护的功能和LOG日志记录功能
wget http://npmjs.org/install.sh --no-check-certificate
sh install.sh -- install nodejs first
[sudo] npm install forever
forever start stats.js config.js
forever list
[0] stats.js [ 24597, 24596 ]
看日志 forever -o out.log -e err.log stats.js
sudo rpm -ivh grafana-3.1.1-1470047149.x86_64.rpm
启动用户 grafana
服务名称 grafana-server
默认端口 3000
账号 admin
密码 admin
sudo service grafana-server start
下载移步:https://www.influxdata.com/downloads/#influxdb
cat << EOF | sudo tee /etc/yum.repos.d/influxdb.repo
[influxdb]
name = InfluxDB Repository - RHEL \$releasever
baseurl = https://repos.influxdata.com/rhel/\$releasever/\$basearch/stable
enabled = 1
gpgcheck = 1
gpgkey = https://repos.influxdata.com/influxdb.key
EOF
sudo yum install influxdb
sudo service influxdb start
InfluxDB内部有支持 graphite的plugin。 修改配置文件 /etc/influxdb/influxdb.conf 的graphite section, 增加相关的template
[[graphite]]
enabled = true
database = "mydb"
bind-address = ":2003"
protocol = "tcp"
consistency-level = "one"
# These next lines control how batching works. You should have this enabled
# otherwise you could get dropped metrics or poor performance. Batching
# will buffer points in memory if you have many coming in.
batch-size = 5000 # will flush if this many points get buffered
batch-pending = 10 # number of batches that may be pending in memory
batch-timeout = "1s" # will flush at least this often even if we haven't hit buffer limit
udp-read-buffer = 0 # UDP Read buffer size, 0 means OS default. UDP listener will fail if set above OS max.
# This string joins multiple matching 'measurement' values providing more control over the final measurement name.
separator = "."
# Default tags that will be added to all metrics. These can be overridden at the template level
# or by tags extracted from metric
#tags = ["region=us-east", "zone=1c"]
# Each template line requires a template pattern. It can have an optional
# filter before the template and separated by spaces. It can also have optional extra
# tags following the template. Multiple tags should be separated by commas and no spaces
# similar to the line protocol format. There can be only one default template.
templates = [
## stats.company.services.facade.apay.PayFacade.*
#"stats.company.services.facade.* ....measurement.servicename.facadename.field",
"stats.*.services.facade.* .measurement...servicename.facadename.method",
## stats_counts.company.services.facade.servicename.facadename.methodname
"stats_counts.*.services.facade.* measurement.measurement...servicename.facadename.method",
## stats.timers.company.services.facade.apay.PayFacade.*.mean
"stats.timers.*.services.facade.* .measurement.measurement...servicename.facadename.methodname.field",
]