热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

快速构建业务监控体系,观grafana监控的艺术

做一个系统,如果不做监控,是不完善的。如果为做一个快速系统,花力气去做监控,是不值得的。(监控系统不是你想做,想做就能做的。)因此,我们有必要具备一个能够快速建立监控体系的能

  做一个系统,如果不做监控,是不完善的。

  如果为做一个快速系统,花力气去做监控,是不值得的。(监控系统不是你想做,想做就能做的。)

 

  因此,我们有必要具备一个能够快速建立监控体系的能力。即使你只是一个普通开发人员!(说不定明天就要叫你去领兵大操练呢)

 

个人觉得,做监控要有三个核心能力:

  1. 持续收集数据的能力; (时间序列数据库)
  2. 监控结果可视化的能力;
  3. 异常监控可报警的能力;

  只要把这三点做到了,那么,这个监控基本就成功了。

 

  既然自己不方便做监控系统,那就只要做好框架选型就可以了。

  因grafana的图表功能个人感觉最强大,我们就以 grafana 作为监控抓手点,创建自己的监控体系吧!

 

监控体系大体实现思路:

  1. 代码里写入埋点,或者其他系统通过探针之类的工具实现数据源;
  2. 监控数据中心接收埋点数据等指标数据集;
  3. 监控中心提供各种维度数据的计算汇总指标;
  4. 自定义图表展现;
  5. 根据结果设置报警;

 

具体打开方法:

  1. 写代码添加埋点;
  2. 使用jmx采集工具采集数据;
  3. 安装 prometheus, 配置好要调用的客户端;
  4. 安装grafana;
  5. 配置 prometheus 的数据源到 grafana 上;
  6. 添加 grafana 监控图表;
  7. 配置监控报警(一般你需要先配置linux邮件设置);

 

所以,看下具体怎么做吧,涉及到安装的部分就顺带过吧,毕竟其他地方,此类信息已经泛滥了!

 

1. 撸埋点代码(jmx)

  .1 引入依赖包

        
        <dependency>
            <groupId>io.dropwizard.metricsgroupId>
            <artifactId>metrics-coreartifactId>
            <version>4.0.0version>
        dependency>
        <dependency>
            <groupId>io.dropwizard.metricsgroupId>
            <artifactId>metrics-jmxartifactId>
            <version>4.0.0version>
        dependency>

  .2 封装指标上报工具类

import com.codahale.metrics.Meter;
import com.codahale.metrics.MetricRegistry;
import com.codahale.metrics.jmx.JmxReporter;
import org.springframework.stereotype.Component;

/**
 * 系统指标管理管理器实现类
 *
 */
@Component
public class SystemMetricsManagerImpl implements SystemMetricsManager {

    private static final MetricRegistry metricsCOntainer= new MetricRegistry();

    static {
        JmxReporter jmxReporter = JmxReporter.forRegistry(metricsContainer).build();
        jmxReporter.start();
    }

    @Override
    public Meter registerAndGetMetricMeter(String meterName) {
        return metricsContainer.meter(meterName);
    }
}

  .3 在需要的地方添加埋点

    // 在必要的地方,进行集中初始化
    @Override
    public void afterPropertiesSet() throws Exception {
        consumeCounterHolder = new ConsumeCounterHolder();
        consumeCounterHolder.initCounter();
    }

    /**
     * 计数器容器实例
     */
    private ConsumeCounterHolder consumeCounterHolder;

    /**
     * 消费计数器容器,作为内部封装,如觉得不爽,也可以抽离为独立对象隔离
     */
    class ConsumeCounterHolder {

        /**
         * 所有消费计数器
         */
        private Meter totalConsumeCounter;

        /**
         * 被抛弃的消费计数器
         */
        private Meter msgDiscardConsumeCounter;

        /**
         * 系统异常消费计数器
         */
        private Meter systemExceptionConsumeCounter;

        /**
         * 业务消费失败,回滚计数器 (一般不会存在值)
         */
        private Meter processFailedConsumeCounter;

        /**
         * 停止消费计数器
         */
        private Meter listenerStoppedConsumeCounter;

        /**
         * 未知类型消费数计数器
         */
        private Meter unknownTypeConsumeCounter;

        /**
         * 初始化计数器
         */
        public void initCounter() {
            totalConsumeCounter = systemMetricsManager.registerAndGetMetricMeter(
                    SystemMetricsConstants.MqConsumeCounter.TOTAL_COUNT_METRIC_NAME);
            msgDiscardConsumeCounter = systemMetricsManager.registerAndGetMetricMeter(
                    SystemMetricsConstants.MqConsumeCounter.DISCARD_COUNT_METRIC_NAME);
            systemExceptionConsumeCounter = systemMetricsManager.registerAndGetMetricMeter(
                    SystemMetricsConstants.MqConsumeCounter.SYSTEM_EXCEPTION_COUNT_METRIC_NAME);
            processFailedConsumeCounter = systemMetricsManager.registerAndGetMetricMeter(
                    SystemMetricsConstants.MqConsumeCounter.PROCESS_FAILED_COUNT_METRIC_NAME);
            listenerStoppedConsumeCounter = systemMetricsManager.registerAndGetMetricMeter(
                    SystemMetricsConstants.MqConsumeCounter.LISTENER_STOPPED_COUNT_METRIC_NAME);
            unknownTypeConsumeCounter = systemMetricsManager.registerAndGetMetricMeter(
                    SystemMetricsConstants.MqConsumeCounter.UNKNOWN_TYPE_COUNT_METRIC_NAME);
        }

        /**
         * 增加消费计数
         */
        private void incTotalConsumeCounter() {
            totalConsumeCounter.mark();
        }
        public void incMsgDiscardConsumeCounter() {
            msgDiscardConsumeCounter.mark();
        }
        public void incSystemExceptionConsumeCounter() {
            systemExceptionConsumeCounter.mark();
        }
        public void incProcessFailedConsumeCounter() {
            processFailedConsumeCounter.mark();
        }
        public void incListenerStoppedConsumeCounter() {
            listenerStoppedConsumeCounter.mark();
        }
        public void incUnknownTypeConsumeCounter() {
            unknownTypeConsumeCounter.mark();
        }
    }

    /**
     * 业务方法中,调用埋点
     *
     */
    public void doSth() {
        // 添加各种埋点
        consumeCounterHolder.incTotalConsumeCounter();
    }

 

2. 使用jmx采集工具采集数据 (prometheus)

  prometheus 作为流行的监控组件,可以很方便的接入 jmx 数据, 使用 jmxReporter 就可以了。

  prometheus 项目地址: https://github.com/prometheus

  jmxReporter 项目地址: https://github.com/prometheus/jmx_exporter

  下载 jmxReporter agent: https://repo1.maven.org/maven2/io/prometheus/jmx/jmx_prometheus_javaagent/0.11.0/jmx_prometheus_javaagent-0.11.0.jar

  添加最简单的配置文件,采集所有jmx数据:

# vim config.yaml
---
rules:
- pattern: ".*"

  最后,启动 jmxReporter, 提供采集依据:

    java -javaagent:./jmx_prometheus_javaagent-0.11.0.jar=9088:config.yaml -jar yourJar.jar

  注: jmxReporter 的原理其实是开启一个http的socket端口,在外部请求进来之后,进行访问jmx数据进行返回。

 

3. 安装prometheus服务端,进行主动数据采集

  .1 下载: https://prometheus.io/download/ , 找到对应版本下载即可;
  .2 直接启动验证下: ./prometheus --config.file=prometheus.yml --web.enable-admin-api
  .3 向 prometheus 中添加客户端机器地址,以便采集,我们只使用一种简单的独立文件的配置方式:

# 1. 直接在文件末尾添加job即可, 此处我们只考虑使用 加载文件 的方式,进行配置,其他配置方式请参考官网
  - job_name: 'jmx'

    file_sd_configs:
    - files:
      - conf.d/test.json

# 2. 在 conf.d/test.json 中,添加相应的客户端机器ip,可以添加其他属性,以便在 grafana上进行友好展示
[
    {
        "targets": ["10.1.1.1:9088"]
    },{
        "targets": ["10.1.1.2:9088"]
    },{
        "targets": ["10.1.1.3:9088"]
    }
]

 

  .4 重启 prometheus(并没有找到优雅重启方法)

    kill -9 xxx
    ./prometheus --config.file=prometheus.yml --web.enable-admin-api

  如此, prometheus 的数据库中就已经有 你的埋点数据了!

 

4. 安装 grafana

  .1 下载地址: https://grafana.com/get
  .2 可以直接使用镜像源安装,也可以使用源码包自行编译;
  .3 启动 grafana 服务: service grafana-server start
  .4 你就可以打开 grafana 后台进行查看了(默认账号密码是 admin/admin);

 

5. 新增 prometheus 作为 grafana 的数据源

  grafana 支持很多数据源的接入,但是 prometheus 是比较简单的一种;

  在设置 -> DataSources 中,添加 prometheus 的数据,按要求填写即可,一般只需要填写一个 prometheus 的请求地址就可以了。

  

6. 添加 grafana 监控图表

  直接点击 + 号,添加一个大盘;

  然后就是各种页面拖拉拽!

  拿几个需要注意的指标统计说明下:

# case1. 代码中的埋点为一个递增的值,我想知道每段时间的增长趋势是怎么样的?如: 1分钟 
    increase(metrics_test_mq_consume_total_Count[1m])
# case2. 在集群环境中,以上统计将是所有机器的总和,我想查看单个机器的增长趋势?
    increase(metrics_test_mq_consume_total_Count{instance=~"$instance_cust"}[1m])    # 其中 instance_cust 是定义在监控大盘上的自定义变量,其作用是 当前监控的实例的标识, 稍后我们看下实例
# case3. 我想知道下当前机器的cpu负载
    avg_over_time(java_lang_OperatingSystem_SystemCpuLoad{instance=~"$instance_cust"}[1m]) * 100 # case4. 我想查看当前机器的物理内存情况
    java_lang_OperatingSystem_FreePhysicalMemorySize{instance=~"$instance_cust"}
    java_lang_OperatingSystem_TotalPhysicalMemorySize{instance=~"$instance_cust"}
# case5. 我想查看jvm的内存情况 
    java_lang_Memory_HeapMemoryUsage_max{instance=~"$instance_cust"}
    java_lang_Memory_HeapMemoryUsage_used{instance=~"$instance_cust"}
    
 # 附: 添加大盘 通用变量
    label_values(up{job='jmx'}, instance) 将会查询符合过滤条件的标签
    

 

  附: 添加大盘 通用变量

  label_values(up{job='jmx'}, instance) 将会查询符合过滤条件的标签

 

7. 配置监控报警(一般你需要先配置linux邮件设置)

  以上都配置好之后,还可以进行报警配置。

  alerting -> Notification Channels 中,添加告警通知通道。

  然后,在原来的大盘中选择一个指标进行报警设置;然后就可以接收告警了。

 

  当然,这里选择邮件,需要linux系统直接使用 mail 进行发送邮件才行。

  

   如此,一个完整的监控链完成!

 

老话: 愿你戎马半生,归来仍是少年。


推荐阅读
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • 本文讨论了如何优化解决hdu 1003 java题目的动态规划方法,通过分析加法规则和最大和的性质,提出了一种优化的思路。具体方法是,当从1加到n为负时,即sum(1,n)sum(n,s),可以继续加法计算。同时,还考虑了两种特殊情况:都是负数的情况和有0的情况。最后,通过使用Scanner类来获取输入数据。 ... [详细]
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
  • Java太阳系小游戏分析和源码详解
    本文介绍了一个基于Java的太阳系小游戏的分析和源码详解。通过对面向对象的知识的学习和实践,作者实现了太阳系各行星绕太阳转的效果。文章详细介绍了游戏的设计思路和源码结构,包括工具类、常量、图片加载、面板等。通过这个小游戏的制作,读者可以巩固和应用所学的知识,如类的继承、方法的重载与重写、多态和封装等。 ... [详细]
  • 阿,里,云,物,联网,net,core,客户端,czgl,aliiotclient, ... [详细]
  • 在说Hibernate映射前,我们先来了解下对象关系映射ORM。ORM的实现思想就是将关系数据库中表的数据映射成对象,以对象的形式展现。这样开发人员就可以把对数据库的操作转化为对 ... [详细]
  • 本文介绍了Oracle数据库中tnsnames.ora文件的作用和配置方法。tnsnames.ora文件在数据库启动过程中会被读取,用于解析LOCAL_LISTENER,并且与侦听无关。文章还提供了配置LOCAL_LISTENER和1522端口的示例,并展示了listener.ora文件的内容。 ... [详细]
  • 本文介绍了Hyperledger Fabric外部链码构建与运行的相关知识,包括在Hyperledger Fabric 2.0版本之前链码构建和运行的困难性,外部构建模式的实现原理以及外部构建和运行API的使用方法。通过本文的介绍,读者可以了解到如何利用外部构建和运行的方式来实现链码的构建和运行,并且不再受限于特定的语言和部署环境。 ... [详细]
  • 本文介绍了一个在线急等问题解决方法,即如何统计数据库中某个字段下的所有数据,并将结果显示在文本框里。作者提到了自己是一个菜鸟,希望能够得到帮助。作者使用的是ACCESS数据库,并且给出了一个例子,希望得到的结果是560。作者还提到自己已经尝试了使用"select sum(字段2) from 表名"的语句,得到的结果是650,但不知道如何得到560。希望能够得到解决方案。 ... [详细]
  • 自动轮播,反转播放的ViewPagerAdapter的使用方法和效果展示
    本文介绍了如何使用自动轮播、反转播放的ViewPagerAdapter,并展示了其效果。该ViewPagerAdapter支持无限循环、触摸暂停、切换缩放等功能。同时提供了使用GIF.gif的示例和github地址。通过LoopFragmentPagerAdapter类的getActualCount、getActualItem和getActualPagerTitle方法可以实现自定义的循环效果和标题展示。 ... [详细]
  • 本文详细介绍了Java中vector的使用方法和相关知识,包括vector类的功能、构造方法和使用注意事项。通过使用vector类,可以方便地实现动态数组的功能,并且可以随意插入不同类型的对象,进行查找、插入和删除操作。这篇文章对于需要频繁进行查找、插入和删除操作的情况下,使用vector类是一个很好的选择。 ... [详细]
  • FeatureRequestIsyourfeaturerequestrelatedtoaproblem?Please ... [详细]
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • 前景:当UI一个查询条件为多项选择,或录入多个条件的时候,比如查询所有名称里面包含以下动态条件,需要模糊查询里面每一项时比如是这样一个数组条件:newstring[]{兴业银行, ... [详细]
author-avatar
无为小妮子_373
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有