前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >可扩展多组件监控方案

可扩展多组件监控方案

原创
作者头像
jemuelmiao
修改2021-11-23 13:11:25
4680
修改2021-11-23 13:11:25
举报
文章被收录于专栏:Sun

1、背景

项目开发中经常会用到很多外部组件,比如mongo、mysql、redis等,虽然在公有环境中使用云上的组件一般都会有完整的监控视图,但是有些项目是部署在私有环境中,使用的都是自建组件,没有完整的监控视图,其次,业务侧也希望将所有组件收归到一起进行统一的监控管理,这样就需要业务侧有一个多组件的监控平台,并且能够方便进行扩展。像笔者目前所在的项目组开发的大数据处理平台,使用了很多外部组件,元数据存储方面有:mongo、mysql、elasticsearch、redis、postgres,大数据存储方面有:hadoop(spark、hive、hbase、hdfs、yarn),为了更好的发现和定位问题,我们需要一个统一的监控管理中心。

2、选型

统一监控平台采用业界广泛使用的框架:prometheus+grafana,其在功能和效果方面完全能达到业务侧需求,并且针对这个选型网上有很多开源组件的exporter和对应grafana视图,避免了很多自定义视图的繁琐工作。比如在这里可以找到很多不错的exporter和视图:https://promcat.io/、https://prometheus.io/docs/instrumenting/exporters/。

3、初始方案

Prometheus+grafana工作原理是由prometheus定期拉取其配置的exporter进程的监控数据,然后grafana视图读取prometheus中的监控数据展示出来,如图1所示。既然我们可以从网上下载到个组件exporter和grafana视图,那就只需要启动各组件exporter进程,将进程地址配置到prometheus中进行定期拉取即可,方案很简单也不需要额外写代码,但是缺点是不方便新增和管理组件,像我们平台使用到了很多组件,我们就需要维护很多exporter进程。

图1 初始方案
图1 初始方案

4、改进方案

上面方案因为prometheus直接对接exporter导致维护成本增加,如果在prometheus和exporter之间增加一个中间层进行管理就可以解决这个问题,如图2所示。

图2 改进方案
图2 改进方案

4.1 管理exporter

将所有exporter、grafana视图放在monitor启动目录中,用于自动导入grafana视图、启动exporter进程、检测exporter进程存活状态。

图3 exporter管理目录
图3 exporter管理目录

设计monitor的配置如下:

代码语言:javascript
复制
[Plugin]
  [[Plugin.Instances]]
    Enable = false
    Folder = "Hadoop"
    Title = "Hadoop"
    DashboardDir = "../tools/hadoop"
    Port = 9001
    Command = "nohup python3 %v -cluster %v -nns %v -rms %v -host 0.0.0.0 -port %v &"
    Parameters = [
      "../tools/hadoop/hadoop_jmx_exporter-master/hadoop_jmx_exporter.py",
      "jm-test-emr",
      "http://127.0.0.1:4008/jmx http://127.0.0.1:4008/jmx",
      "http://127.0.0.1:5004/jmx http://127.0.0.1:5004/jmx",
      "9001",
   ]
   ...

4.2 聚合监控数据

Prometheus拉取数据有特定的协议,因此monitor需要汇聚所有exporter的监控数据后按照同样的协议发送给prometheus。

正常情况我们在写业务侧exporter暴露给prometheus时可以通过注册自己的Collector来收集监控数据,但是这里我们需要对接的是其他exporter返回的特定格式数据,为了避免解析数据然后重新格式化,我们可以直接在http层进行聚合然后返回给prometheus。

为了在http层聚合,我们先看看prometheus拉取接口是怎么处理的。下载prometheus的golang库,prometheus拉取监控数据流程为:

  • 注册prometheus请求地址
代码语言:javascript
复制
...
http.NewServeMux().Handle("/metrics", promhttp.Handler())
...
  • 默认请求处理句柄
代码语言:javascript
复制
promhttp.Handler() {
  return InstrumentMetricHandler(
    prometheus.DefaultRegisterer, HandlerFor(prometheus.DefaultGatherer, HandlerOpts{}),
  )
}
promhttp.HandlerFor() {
  ...
  //收集数据
  mfs, err := reg.Gather()
  //获取回包编码
  enc := expfmt.NewEncoder(w, contentType)
  //编码所有数据返回prometheus
  for _, mf := range mfs {
    if enc.Encode(mf) {
      return
    }
  }
  ...
}

从上面的流程可以看出,我们只需要重写HandlerFor,将各组件exporter的回包拼接后返回prometheus就可以完成数据汇聚,简化代码如下:

代码语言:javascript
复制
promhttp.HandlerFor() {
  ...
  //收集数据
  mfs, err := reg.Gather()
  //获取回包编码
  enc := expfmt.NewEncoder(w, contentType)
  //编码所有数据返回prometheus
  for _, mf := range mfs {
    if enc.Encode(mf) {
      return
    }
  }
  //加上其他exporter数据回包并返回
  var wg sync.WaitGroup
  var rsps [][]byte
  for _, p := range plugins {
    wg.Add(1)
    go func(plugin *Plugin) {
      defer wg.Done()
      body, e := HttpGet(plugin.Url, nil, nil, nil, 0)
      if e == nil && len(body) > 0 {
        body = append(body, '\n')
        rsps = append(rsps, body)
      }
    }(p)
  }
  wg.Wait()
  for _, rsp := range rsps {
    w.Write(rsp)
  }
  ...
}

5、实际效果

图4 各组件监控列表
图4 各组件监控列表
图5 Redis组件监控
图5 Redis组件监控
图6 MySQL组件监控
图6 MySQL组件监控

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1、背景
  • 2、选型
  • 3、初始方案
  • 4、改进方案
    • 4.1 管理exporter
      • 4.2 聚合监控数据
      • 5、实际效果
      相关产品与服务
      云数据库 Redis
      腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档