zoukankan      html  css  js  c++  java
  • 快速构建业务监控体系,观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 引入依赖包

            <!-- jmx 埋点依赖 -->
            <dependency>
                <groupId>io.dropwizard.metrics</groupId>
                <artifactId>metrics-core</artifactId>
                <version>4.0.0</version>
            </dependency>
            <dependency>
                <groupId>io.dropwizard.metrics</groupId>
                <artifactId>metrics-jmx</artifactId>
                <version>4.0.0</version>
            </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) 将会查询符合过滤条件的标签
        

      附: 添加大盘 通用变量

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

      2. 当有很多label时,只想显示一两个,则可以在 标题栏写入 {{label_name}}, 进行简化展示。比如,使用 {{instance}} 显示 实例ip 信息, 如果你有一个 topic的 label则可以这样显示 {{topic}}。

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

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

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

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

     

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

      

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

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

  • 相关阅读:
    《Windows核心编程系列》十四谈谈默认堆和自定义堆
    《windows核心编程系列》十五谈谈windows线程栈
    《Windows核心编程系列》十三谈谈在应用程序中使用虚拟内存
    《Windows核心编程系列》十二谈谈Windows内存体系结构
    《Windows核心编程系列》十一谈谈Windows线程池
    Extjs利用vtype验证表单
    Extjs文本输入框
    Extjs文本输入域
    远程数据源Combobox
    Extjs整体加载树节点
  • 原文地址:https://www.cnblogs.com/yougewe/p/11140129.html
Copyright © 2011-2022 走看看