• 聊聊springboot的TomcatMetricsBinder


    本文主要研究一下springboot的TomcatMetricsBinder

    TomcatMetricsAutoConfiguration

    org/springframework/boot/actuate/autoconfigure/metrics/web/tomcat/TomcatMetricsAutoConfiguration.java

    @Configuration(proxyBeanMethods = false)
    @ConditionalOnWebApplication
    @ConditionalOnClass({ TomcatMetrics.class, Manager.class })
    @AutoConfigureAfter(CompositeMeterRegistryAutoConfiguration.class)
    public class TomcatMetricsAutoConfiguration {
    
    	@Bean
    	@ConditionalOnBean(MeterRegistry.class)
    	@ConditionalOnMissingBean({ TomcatMetrics.class, TomcatMetricsBinder.class })
    	public TomcatMetricsBinder tomcatMetricsBinder(MeterRegistry meterRegistry) {
    		return new TomcatMetricsBinder(meterRegistry);
    	}
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    TomcatMetricsAutoConfiguration在CompositeMeterRegistryAutoConfiguration之后自动配置,它会创建TomcatMetricsBinder

    TomcatMetricsBinder

    org/springframework/boot/actuate/metrics/web/tomcat/TomcatMetricsBinder.java

    public class TomcatMetricsBinder implements ApplicationListener, DisposableBean {
    
    	private final MeterRegistry meterRegistry;
    
    	private final Iterable tags;
    
    	private volatile TomcatMetrics tomcatMetrics;
    
    	public TomcatMetricsBinder(MeterRegistry meterRegistry) {
    		this(meterRegistry, Collections.emptyList());
    	}
    
    	public TomcatMetricsBinder(MeterRegistry meterRegistry, Iterable tags) {
    		this.meterRegistry = meterRegistry;
    		this.tags = tags;
    	}
    
    	@Override
    	public void onApplicationEvent(ApplicationStartedEvent event) {
    		ApplicationContext applicationContext = event.getApplicationContext();
    		Manager manager = findManager(applicationContext);
    		this.tomcatMetrics = new TomcatMetrics(manager, this.tags);
    		this.tomcatMetrics.bindTo(this.meterRegistry);
    	}
    
    	private Manager findManager(ApplicationContext applicationContext) {
    		if (applicationContext instanceof WebServerApplicationContext) {
    			WebServer webServer = ((WebServerApplicationContext) applicationContext).getWebServer();
    			if (webServer instanceof TomcatWebServer) {
    				Context context = findContext((TomcatWebServer) webServer);
    				return context.getManager();
    			}
    		}
    		return null;
    	}
    
    	private Context findContext(TomcatWebServer tomcatWebServer) {
    		for (Container container : tomcatWebServer.getTomcat().getHost().findChildren()) {
    			if (container instanceof Context) {
    				return (Context) container;
    			}
    		}
    		return null;
    	}
    
    	@Override
    	public void destroy() {
    		if (this.tomcatMetrics != null) {
    			this.tomcatMetrics.close();
    		}
    	}
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53

    TomcatMetricsBinder实现了ApplicationListener监听ApplicationStartedEvent,同时也实现了DisposableBean接口;其onApplicationEvent方法会获取applicationContext再获取tomcat的Manager,最后创建tomcatMetrics,然后执行bindTo方法;其close方法主要是执行tomcatMetrics的close方法

    TomcatMetrics

    io/micrometer/core/instrument/binder/tomcat/TomcatMetrics.java

    @NonNullApi
    @NonNullFields
    public class TomcatMetrics implements MeterBinder {
    
        private static final String JMX_DOMAIN_EMBEDDED = "Tomcat";
        private static final String JMX_DOMAIN_STANDALONE = "Catalina";
        private static final String OBJECT_NAME_SERVER_SUFFIX = ":type=Server";
        private static final String OBJECT_NAME_SERVER_EMBEDDED = JMX_DOMAIN_EMBEDDED + OBJECT_NAME_SERVER_SUFFIX;
        private static final String OBJECT_NAME_SERVER_STANDALONE = JMX_DOMAIN_STANDALONE + OBJECT_NAME_SERVER_SUFFIX;
    
        @Nullable
        private final Manager manager;
    
        private final MBeanServer mBeanServer;
        private final Iterable tags;
    
        private volatile String jmxDomain;
    
        @Override
        public void bindTo(MeterRegistry registry) {
            registerGlobalRequestMetrics(registry);
            registerServletMetrics(registry);
            registerCacheMetrics(registry);
            registerThreadPoolMetrics(registry);
            registerSessionMetrics(registry);
        }
    
        //......
    }            
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    TomcatMetrics实现了MeterBinder接口,其bindTo方法主要是执行了registerGlobalRequestMetrics、registerServletMetrics、registerCacheMetrics、registerThreadPoolMetrics、registerSessionMetrics

    registerGlobalRequestMetrics

        private void registerGlobalRequestMetrics(MeterRegistry registry) {
            registerMetricsEventually("type", "GlobalRequestProcessor", (name, allTags) -> {
                FunctionCounter.builder("tomcat.global.sent", mBeanServer,
                    s -> safeDouble(() -> s.getAttribute(name, "bytesSent")))
                    .tags(allTags)
                    .baseUnit(BaseUnits.BYTES)
                    .register(registry);
    
                FunctionCounter.builder("tomcat.global.received", mBeanServer,
                    s -> safeDouble(() -> s.getAttribute(name, "bytesReceived")))
                    .tags(allTags)
                    .baseUnit(BaseUnits.BYTES)
                    .register(registry);
    
                FunctionCounter.builder("tomcat.global.error", mBeanServer,
                        s -> safeDouble(() -> s.getAttribute(name, "errorCount")))
                        .tags(allTags)
                        .register(registry);
    
                FunctionTimer.builder("tomcat.global.request", mBeanServer,
                        s -> safeLong(() -> s.getAttribute(name, "requestCount")),
                        s -> safeDouble(() -> s.getAttribute(name, "processingTime")), TimeUnit.MILLISECONDS)
                        .tags(allTags)
                        .register(registry);
    
                TimeGauge.builder("tomcat.global.request.max", mBeanServer, TimeUnit.MILLISECONDS,
                        s -> safeDouble(() -> s.getAttribute(name, "maxTime")))
                        .tags(allTags)
                        .register(registry);
            });
        }    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    registerGlobalRequestMetrics主要是注册了请求相关的指标

    registerServletMetrics

        private void registerServletMetrics(MeterRegistry registry) {
            registerMetricsEventually("j2eeType", "Servlet", (name, allTags) -> {
                FunctionCounter.builder("tomcat.servlet.error", mBeanServer,
                        s -> safeDouble(() -> s.getAttribute(name, "errorCount")))
                        .tags(allTags)
                        .register(registry);
    
                FunctionTimer.builder("tomcat.servlet.request", mBeanServer,
                        s -> safeLong(() -> s.getAttribute(name, "requestCount")),
                        s -> safeDouble(() -> s.getAttribute(name, "processingTime")), TimeUnit.MILLISECONDS)
                        .tags(allTags)
                        .register(registry);
    
                TimeGauge.builder("tomcat.servlet.request.max", mBeanServer, TimeUnit.MILLISECONDS,
                        s -> safeDouble(() -> s.getAttribute(name, "maxTime")))
                        .tags(allTags)
                        .register(registry);
            });
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    registerServletMetrics主要是注册了servlet相关的errorCount、requestCount及maxTime

    registerCacheMetrics

        private void registerCacheMetrics(MeterRegistry registry) {
            registerMetricsEventually("type", "StringCache", (name, allTags) -> {
                FunctionCounter.builder("tomcat.cache.access", mBeanServer,
                        s -> safeDouble(() -> s.getAttribute(name, "accessCount")))
                        .tags(allTags)
                        .register(registry);
    
                FunctionCounter.builder("tomcat.cache.hit", mBeanServer,
                        s -> safeDouble(() -> s.getAttribute(name, "hitCount")))
                        .tags(allTags)
                        .register(registry);
            });
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    registerCacheMetrics主要是注册了tomcat内部cache的accessCount、hitCount

    registerThreadPoolMetrics

        private void registerThreadPoolMetrics(MeterRegistry registry) {
            registerMetricsEventually("type", "ThreadPool", (name, allTags) -> {
                Gauge.builder("tomcat.threads.config.max", mBeanServer,
                        s -> safeDouble(() -> s.getAttribute(name, "maxThreads")))
                        .tags(allTags)
                        .baseUnit(BaseUnits.THREADS)
                        .register(registry);
    
                Gauge.builder("tomcat.threads.busy", mBeanServer,
                        s -> safeDouble(() -> s.getAttribute(name, "currentThreadsBusy")))
                        .tags(allTags)
                        .baseUnit(BaseUnits.THREADS)
                        .register(registry);
    
                Gauge.builder("tomcat.threads.current", mBeanServer,
                        s -> safeDouble(() -> s.getAttribute(name, "currentThreadCount")))
                        .tags(allTags)
                        .baseUnit(BaseUnits.THREADS)
                        .register(registry);
            });
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    registerThreadPoolMetrics主要是注册了tomcat线程池的相关指标

    registerSessionMetrics

        private void registerSessionMetrics(MeterRegistry registry) {
            if (manager == null) {
                // If the binder is created but unable to find the session manager don't register those metrics
                return;
            }
    
            Gauge.builder("tomcat.sessions.active.max", manager, Manager::getMaxActive)
                    .tags(tags)
                    .baseUnit("sessions")
                    .register(registry);
    
            Gauge.builder("tomcat.sessions.active.current", manager, Manager::getActiveSessions)
                    .tags(tags)
                    .baseUnit("sessions")
                    .register(registry);
    
            FunctionCounter.builder("tomcat.sessions.created", manager, Manager::getSessionCounter)
                    .tags(tags)
                    .baseUnit("sessions")
                    .register(registry);
    
            FunctionCounter.builder("tomcat.sessions.expired", manager, Manager::getExpiredSessions)
                    .tags(tags)
                    .baseUnit("sessions")
                    .register(registry);
    
            FunctionCounter.builder("tomcat.sessions.rejected", manager, Manager::getRejectedSessions)
                    .tags(tags)
                    .baseUnit("sessions")
                    .register(registry);
    
            TimeGauge.builder("tomcat.sessions.alive.max", manager, TimeUnit.SECONDS, Manager::getSessionMaxAliveTime)
                    .tags(tags)
                    .register(registry);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    registerSessionMetrics主要是注册了tomcat的session相关指标

    小结

    springboot的TomcatMetricsBinder主要是接收ApplicationStartedEvent然后创建TomcatMetrics执行bindTo进行注册,TomcatMetrics主要注册了globalRequest、servlet、cache、threadPool、session相关的指标。

  • 相关阅读:
    docker 构建jar包/vue镜像以及发布
    volatile
    E (1081) : DS堆栈--逆序输出(STL栈使用)
    uniapp----微信小程序 日历组件(周日历&& 月日历)【Vue3+ts+uView】
    角谱迭代与傅里叶变换迭代算法(GS)的原理及其实例演示分析
    第14讲:DCL类型的SQL语句之用户管理
    手把手教你一键部署自己的HTML静态网页
    scipy库统计模块stats
    Python调用webservice接口
    QT快速入门
  • 原文地址:https://blog.csdn.net/hello_ejb3/article/details/134068934