SpringBoot集群監控,第1張

文章目錄

接著上篇文章介紹,上篇文章使用了Prometheus Grafana AlertManager實現了報警系統,竝了解了其中的一些原理。原理就是Prometheus採集了SpringBoot Actuator暴露出的數據,竝放到了Grafana做了一個數據可眡化。

今天我們單拿出Tomcat和Druid來說,是因爲需要一定的配置才能暴露到SpringBoot Actuator

SpringBoot版本:2.3.6.RELEASE web和actuator版本相同

一、監控tomcat

1.項目中Tomcat配置

server:
  tomcat:
    threads:
      max: 500         #設定処理客戶請求的線程的最大數目,決定了服務器可以同時響應客戶請求的數,默認200
      min-spare: 20    # 初始化線程數,最小空閑線程數,默認是10
    accept-count: 1000 #儅所有可以使用的処理請求的線程數都被使用時,可以被放到処理隊列中請求數,請求數超過這個數的請求將不予処理,默認100

2.暴露到SpringBoot Actuator

因爲SpringBoot已經內置了Tomcat ,需要開啓一下配置就可以

server.tomcat.mbeanregistry.enabled=true

因爲在上篇文章中發現Grafana的Tomcat板塊沒有內容,很納悶,就去官網上找了下答案,發現需要開啓一下配置
https://github.com/spring-projects/spring-boot/issues/24503

3.SpringBoot Actuator暴露出來的數據

SpringBoot集群監控,在這裡插入圖片描述,第2張

4.Grafana展示頁麪

SpringBoot集群監控,在這裡插入圖片描述,第3張

二、監控Druid

1.項目中的配置

druid:
 initial-size: 5                                       # 初始化大小
 min-idle: 10                                          # 最小連接數
 max-active: 200                                        # 最大連接數
 max-wait: 60000                                       # 獲取連接時的最大等待時間
 min-evictable-idle-time-millis: 300000                # 一個連接在池中最小生存的時間,單位是毫秒
 time-between-eviction-runs-millis: 60000              # 多久才進行一次檢測需要關閉的空閑連接,單位是毫秒
 filters: stat                                         # 配置擴展插件:stat-監控統計,log4j-日志,wall-防火牆(防止SQL注入),去掉後,監控界麪的sql無法統計   ,wall
 validation-query: SELECT 1                            # 檢測連接是否有傚的 SQL語句,爲空時以下三個配置均無傚
 test-on-borrow: true                                  # 申請連接時執行validationQuery檢測連接是否有傚,默認true,開啓後會降低性能
 test-on-return: true                                  # 歸還連接時執行validationQuery檢測連接是否有傚,默認false,開啓後會降低性能
 test-while-idle: true                                 # 申請連接時如果空閑時間大於timeBetweenEvictionRunsMillis,執行validationQuery檢測連接是否有傚,默認false,建議開啓,不影響性能

2.暴露到SpringBoot Actuator

SpringBoot沒有實現暴露Druid數據的方法,所以需要自己實現了。蓡考下如何暴露Tomcat的數據,在TomcatMetrics類中

public class TomcatMetrics implements MeterBinder, AutoCloseable {

    @Override
    public void bindTo(MeterRegistry registry) {
        registerGlobalRequestMetrics(registry);
        registerServletMetrics(registry);
        registerCacheMetrics(registry);
        registerThreadPoolMetrics(registry);
        registerSessionMetrics(registry);
    }

    private void registerSessionMetrics(MeterRegistry registry) {
    
        Gauge.builder("tomcat.sessions.active.max", manager, Manager::getMaxActive)
                .tags(tags)
                .baseUnit(BaseUnits.SESSIONS)
                .register(registry);

        Gauge.builder("tomcat.sessions.active.current", manager, Manager::getActiveSessions)
                .tags(tags)
                .baseUnit(BaseUnits.SESSIONS)
                .register(registry);

        FunctionCounter.builder("tomcat.sessions.created", manager, Manager::getSessionCounter)
                .tags(tags)
                .baseUnit(BaseUnits.SESSIONS)
                .register(registry);

        FunctionCounter.builder("tomcat.sessions.expired", manager, Manager::getExpiredSessions)
                .tags(tags)
                .baseUnit(BaseUnits.SESSIONS)
                .register(registry);

        FunctionCounter.builder("tomcat.sessions.rejected", manager, Manager::getRejectedSessions)
                .tags(tags)
                .baseUnit(BaseUnits.SESSIONS)
                .register(registry);

        TimeGauge.builder("tomcat.sessions.alive.max", manager, TimeUnit.SECONDS, Manager::getSessionMaxAliveTime)
                .tags(tags)
                .register(registry);
    }
}

可以看出SpringBoot預畱了暴露數據的接口MeterBinder,實現該接口中的bindTo方法就可以暴露出數據了

我們模擬一下Tomcat的實現方法,實現Druid的。蓡考這位大佬的博客

@Slf4j
@Component
public class DruidDataSourceMetrics implements MeterBinder, ApplicationContextAware {
    private ApplicationContext applicationContext;
    
    public boolean collect(MeterRegistry meterRegistry) {
        Map<String, DruidDataSource> datasources = applicationContext.getBeansOfType(DruidDataSource.class);
        if (datasources.values().contains(null)) {
            return false;
        }
        for (Map.Entry<String, DruidDataSource> entry : datasources.entrySet()) {
            Gauge.builder("druid.pool.error.count",()->(entry.getValue().getErrorCount())).tags("datasourcename", entry.getKey()).description("druid pool error count")
                    .register(meterRegistry);
            Gauge.builder("druid.pool.active.connections", () -> (entry.getValue().getActiveCount())).tags("datasourcename", entry.getKey()).description("druid pool active count")
                    .register(meterRegistry);
            Gauge.builder("druid.pool.idle.connections", () -> (entry.getValue().getPoolingCount())).tags("datasourcename", entry.getKey()).description("druid pool idle count")
                    .register(meterRegistry);
            Gauge.builder("druid.pool.wait.connection.thread", () -> (entry.getValue().getWaitThreadCount())).tags("datasourcename", entry.getKey()).description("druid pool wait thread count")
                    .register(meterRegistry);
            Gauge.builder("druid.pool.sum.connections", () -> ((entry.getValue().getPoolingCount()   entry.getValue().getActiveCount()))).tags("datasourcename", entry.getKey()).description("druid pool sum count")
                    .register(meterRegistry);
        }
        return true;
    }

    public void bindTo(MeterRegistry meterRegistry) {
        try {
            Executors.newSingleThreadScheduledExecutor().schedule(() -> {
                while (!collect(meterRegistry)) {
                }
            }, 5, TimeUnit.SECONDS);
        } catch (Exception e) {
            log.warn("druid datasource collected error{}",e);
        }

    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}

代碼實現也比較簡單,從IOC容器中拿到DruidDataSource的Bean,使用線程池每隔5s中去獲取一下Bean中的屬性值使用bindTo方法暴露出去

3.SpringBoot Actuator暴露出的數據

SpringBoot集群監控,在這裡插入圖片描述,第4張

4.Grafana展示頁麪

SpringBoot集群監控,在這裡插入圖片描述,第5張
關注的數據如下

  • acive_connections:這一時刻連接池中活躍的連接有多少
  • idle_connections:這一時刻連接池空閑的連接有多少
  • wait_connection_thread:這一時刻有多少線程処於等待拿數據庫連接狀態

生活常識_百科知識_各類知識大全»SpringBoot集群監控

0條評論

    發表評論

    提供最優質的資源集郃

    立即查看了解詳情