快速構建業務監控體系,觀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 進行發送郵件才行。

  

   如此,一個完整的監控鏈完成!

 

老話: 願你戎馬半生,歸來仍是少年。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM