聊聊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);}}

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

TomcatMetricsBinder

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

public class TomcatMetricsBinder implements ApplicationListener<ApplicationStartedEvent>, DisposableBean {private final MeterRegistry meterRegistry;private final Iterable<Tag> tags;private volatile TomcatMetrics tomcatMetrics;public TomcatMetricsBinder(MeterRegistry meterRegistry) {this(meterRegistry, Collections.emptyList());}public TomcatMetricsBinder(MeterRegistry meterRegistry, Iterable<Tag> tags) {this.meterRegistry = meterRegistry;this.tags = tags;}@Overridepublic 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;}@Overridepublic void destroy() {if (this.tomcatMetrics != null) {this.tomcatMetrics.close();}}}

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;@Nullableprivate final Manager manager;private final MBeanServer mBeanServer;private final Iterable<Tag> tags;private volatile String jmxDomain;@Overridepublic void bindTo(MeterRegistry registry) {registerGlobalRequestMetrics(registry);registerServletMetrics(registry);registerCacheMetrics(registry);registerThreadPoolMetrics(registry);registerSessionMetrics(registry);}//......
}            

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);});}    

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);});}

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);});}

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);});}

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 metricsreturn;}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);}

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

小结

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/121327.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

pinia全局状态管理

使用&#xff1a;结合vue2、vue3使用 优点&#xff1a;相比vuex&#xff1a;提供组合式和选项式的写法&#xff0c;支持ts类型推断&#xff0c;提供更简洁的状态管理&#xff08;去除mutation&#xff09; 注意点&#xff1a; &#xff08;1&#xff09;使用store时不要结构&am…

Spring Web MVC入门

一&#xff1a;了解Spring Web MVC (1)关于Java开发 &#x1f31f;Java开发大多数场景是业务开发 比如说京东的业务就是电商卖货、今日头条的业务就推送新闻&#xff1b;快手的业务就是短视频推荐 (2)Spring Web MVC的简单理解 &#x1f497;Spring Web MVC&#xff1a;如何使…

分布估计算法(Estimation of distribution algorithm,EDA)

概论 分布估计算法&#xff08;Estimation of distribution algorithm&#xff0c;EDA&#xff09;是一种新兴的基于统计学原理的随机优化算法。 为什么要叫这个名字呢&#xff1f; 首先&#xff0c;“分布”指的就是概率分布。 其次&#xff0c;“估计”指的是这个概率分布…

通过requests库使用HTTP编写的爬虫程序

使用Python的requests库可以方便地编写HTTP爬虫程序。以下是一个使用requests库的示例&#xff1a; import requests# 发送HTTP GET请求 response requests.get("http://example.com")# 检查响应状态码 if response.status_code 200:# 获取响应内容html response.…

Crawler4j实例爬取爱奇艺热播剧案例

前言 热播剧数据在戏剧娱乐产业中扮演着着名的角色。热了解播剧的观众喜好和趋势&#xff0c;对于制作方和广告商来说都具有重要的参考价值。然而&#xff0c;手动收集和整理这些数据是在本文中&#xff0c;我们将介绍如何利用 Python 爬虫技术和 Crawler4j 实例来自动化爬取爱…

对硬件编程的一点理解---vitis使用

硬件的核心是并行编程&#xff0c;它主要包括两大部分&#xff1a;多流水并行、流水内部打拍。 1 多流水并行编程是在硬件内部形成多条流水&#xff0c;和cpu多个核心 类似&#xff0c;但是数量可以远远超过cpu核数&#xff0c;一般实现方案有两种&#xff1a;fifo和ram 1) f…

Docker实战之二

一、前言 前一篇 Docker实战之一 我们介绍了Dokcer 镜像和容器基本概念&#xff0c;这一节我们来具体制作一个镜像文件并进行快速部署&#xff0c;这个镜像文件是我们的测试环境&#xff0c;主要包含JDK1.8、Nginx、Git、Node、Gradle&#xff0c;基础镜像为CentOS&#xff0c…

并查集学习心得

int find(int x)//并查集找父亲 {if(x!fa[x]) fa[x]find(fa[x]);return fa[x]; } void add(int x,int y)//合并 {int fxfind(x);int fyfind(y);if(x!y) fa[fx]fy; } P1197 [JSOI2008] 星球大战 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 洛谷p1197星球大战 :并查集逆向…

Java练习题2020-3

统计从1到N的整数中,所有立方值的平方根为整数的数的个数 输入说明&#xff1a;整数 N(N<10000)&#xff1b; 输出说明&#xff1a;符合条件的数的个数&#xff0c;如4^3648^2 输入样例&#xff1a;10 输出样例&#xff1a;3 (说明&#xff1a;样例中符合条件的3个数是1、4、…

用低代码平台代替Excel搭建进销存管理系统

目录 一、用低代码平台搭建系统 1.需求调研 2.基于痛点梳理业务流程 3.低代码实现 &#xff08;1&#xff09;基础资料模块 &#xff08;2&#xff09;采购管理模块 &#xff08;3&#xff09;销售管理模块 &#xff08;4&#xff09;库存管理模块 &#xff08;5&…

【点云】有序/无序点云区别(详细详解)

&#x1f449;博__主&#x1f448;&#xff1a;米码收割机 &#x1f449;技__能&#x1f448;&#xff1a;C/Python语言 &#x1f449;公众号&#x1f448;&#xff1a;测试开发自动化【获取源码商业合作】 &#x1f449;荣__誉&#x1f448;&#xff1a;阿里云博客专家博主、5…

Windows server部署filebeat到kafka

需求&#xff1a;Windows dhcp日志需要实时传输到elk或者其他告警平台。 1、filebeat下载地址&#xff1a;https://www.elastic.co/cn/downloads/beats/filebeat 2、下载后解压后配置filebeat.yml文件&#xff0c; 3、README.md文件中有运行的操作方法&#xff1a;cmd上进入f…

Redis学习笔记5:基于springboot的lettuce redis客户端断线重连ConnectionWatchdog

lettuce默认采用共享本地连接的模式和redis服务器端交互&#xff0c;如果连接断开如何及时发现并且重新建立连接呢&#xff1f;通过翻阅源码发现有两种方案&#xff0c;方案一&#xff1a;开启连接有效性检测&#xff1b;方案二&#xff1a;通过ConnectionWatchdog监视器 一个对…

为什么网上的流量卡都有禁发地区呢?流量卡管控地区整理!

在网上购买过流量卡的朋友应该都知道&#xff0c;但凡是运营商推出的大流量优惠套餐&#xff0c;在套餐详情中都是有禁发地区&#xff0c;只不过每张卡的禁发地区不同而已。 设置禁发地区的主要目的还是为了防止一些电信诈骗案件的发生&#xff0c;或者违法违规利用电话卡的情…

C语言数据结构之数据结构入门

目录 数据结构介绍 数据结构发展史 何为算法 数据结构基础 基本概念和术语 四大逻辑结构&#xff08;Logic Structure&#xff09; 数据类型 理解复杂度概念 时间空间复杂度定义 度量时间复杂度的方法 程序运行时的内存与地址 编程预备 数据结构介绍 数据结构发展…

CVPR2023新作:基于组合空时位移的视频修复

Title: A Simple Baseline for Video Restoration With Grouped Spatial-Temporal Shift (视频修复的简单基准&#xff1a;组合空时位移) Affiliation: CUHK MMLab (香港中文大学多媒体实验室) Authors: Dasong Li, Xiaoyu Shi, Yi Zhang, Ka Chun Cheung, Simon See, Xiaoga…

苏宁一面复盘

技术问题&#xff08;顺序有错乱&#xff09;&#xff1a; 1.抽象类与接口&#xff0c;什么时候用抽象类&#xff0c;什么时候用接口&#xff0c;区别是什么。 答&#xff1a;抽象类内可以有非抽象方法&#xff0c;方法的具体实现&#xff0c;接口内只能有抽象方法&#xff0…

python:多波段遥感影像分离成单波段影像

作者:CSDN @ _养乐多_ 在遥感图像处理中,我们经常需要将多波段遥感影像拆分成多个单波段图像,以便进行各种分析和后续处理。本篇博客将介绍一个用Python编写的程序,该程序可以读取多波段遥感影像,将其拆分为单波段图像,并保存为单独的文件。本程序使用GDAL库来处理遥感影…

一个简单的注册页面,如有错误请指正(2.css)

这段CSS代码定义了页面的样式&#xff0c;让我逐个解释其功能&#xff1a; 1. * {}&#xff1a;通配符选择器&#xff0c;用于将页面中的所有元素设置统一的样式。这里将margins和paddings设置为0&#xff0c;以去除默认的边距。 2. div img {}&#xff1a;选择页面中所有div…

LMFLOSS:专治解决不平衡医学图像分类的新型混合损失函数 (附代码)

论文地址&#xff1a;https://arxiv.org/pdf/2212.12741.pdf 代码地址&#xff1a;https://github.com/SanaNazari/LMFLoss 1.是什么&#xff1f; LMFLOSS是一种用于不平衡医学图像分类的混合损失函数。它是由Focal Loss和LDAM Loss的线性组合构成的&#xff0c;旨在更好地处…