聊聊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相关的指标。
相关文章:
聊聊springboot的TomcatMetricsBinder
序 本文主要研究一下springboot的TomcatMetricsBinder TomcatMetricsAutoConfiguration org/springframework/boot/actuate/autoconfigure/metrics/web/tomcat/TomcatMetricsAutoConfiguration.java Configuration(proxyBeanMethods false) ConditionalOnWebApplication C…...
《动手学深度学习 Pytorch版》 10.6 自注意力和位置编码
在注意力机制中,每个查询都会关注所有的键-值对并生成一个注意力输出。由于查询、键和值来自同一组输入,因此被称为 自注意力(self-attention),也被称为内部注意力(intra-attention)…...
2023年第四届MathorCup高校数学建模挑战赛——大数据竞赛B题 实现代码
根据之前发布的思路 第一步 进行数据合并 import pandas as pd# 读取所有附件的数据 data1 pd.read_excel(附件一.xlsx) data2 pd.read_excel(附件二.xlsx) data3 pd.read_excel(附件三.xlsx) data4 pd.read_excel(附件四.xlsx)# 根据商品编码将附件一和附件二连接 combi…...
larvel 中的api.php_Laravel 开发 API
Laravel10中提示了Target *classController does not exist,为什么呢? 原因是:laravel8开始写法变了。换成了新的写法了 解决方法一: 在路由数组加入App\Http\Controllers\即可。 <?phpuse Illuminate\Support\Facades\Route;…...
虚拟机构建部署单体项目及前后端分离项目
目录 一.部署单体项目 1.远程数据库 1.1远程连接数据库 1.2 新建数据库运行sql文件 2.部署项目到服务器中 3.启动服务器运行 二.部署前后端分离项目 1.远程数据库和部署到服务器 2.利用node环境启动前端项目 3.解决主机无法解析服务器localhost问题 方法一 编辑 方法二 一.部…...
C++之特殊类的设计
目录 一、单例模式 1、设计模式 2、单例模式 1、饿汉模式 2、懒汉模式 3、单例对象的释放问题 二、设计一个不能被拷贝的类 三、设计一个只能在堆上创建对象的类 四、设计一个只能在栈上创建对象的类 五、设计一个不能被继承的类 一、单例模式 1、设计模式 概念&am…...
Java练习题2020 -1
统计1到N的整数中,被A除余A-1的偶数的个数 输入说明:整数 N(N<10000), A, (A 输出说明:符合条件的数的个数 输入样例:10 3 输出样例:2 (说明:样例中符合条件的2个数是 2、8) import java.util.Scanner;p…...
LuaTable转C#的列表List和字典Dictionary
LuaTable转C#的列表List和字典Dictionaty 介绍lua中创建表测试lua中list表表转成List表转成Dictionary 键值对表表转成Dictionary 多类型键值对表表转成Dictionary 总结 介绍 之前基本都是从C#中的List或者Dictionary转成luaTable,很少会把LuaTable转成C#的List或者…...
Redis快速上手篇七(集群)
在赶工了..... Redis集群 主从复制的场景无法吗满足主机单点故障时需要引入集群配置 一般数据库要处理的读请求远大于写请求 ,针对这种情况,我们优化数据库可以采用读写分离的策略。我们可以部 署一台主服务器主要用来处理写请求,部署多台从…...
Mac 安装nvm
安装方案: 1. 从github下载nvm仓库到 ~/目录 地址:https://github.com/nvm-sh/nvm.git git clone https://github.com/nvm-sh/nvm.git 2. 进入nvm目录中执行install.sh等待执行完成,执行的操作方法就是直接将文件拖入到终端然后回车。 3.…...
python 从mssql取出datetime2类型之后格式化
我mssql是datetime2类型,用df取出之后发现是个纳秒的int(1698419713000000000 这种) 所以格式化的话就需要变成秒为单位,他们之间是10的9次方倍。所以先除以1e9之后用datetime.datetime.fromtimestamp()转换之后再format就行了 l…...
18.2 使用NPCAP库抓取数据包
NPCAP 库是一种用于在Windows平台上进行网络数据包捕获和分析的库。它是WinPcap库的一个分支,由Nmap开发团队开发,并在Nmap软件中使用。与WinPcap一样,NPCAP库提供了一些API,使开发人员可以轻松地在其应用程序中捕获和处理网络数据…...
pytest-yaml 测试平台-3.创建执行任务定时执行用例
前言 当项目用例编写完成后,需设置执行策略,可以用到定时任务设置每天几点执行。或者间隔几个小时执行一次。 创建定时任务 创建任务 勾选需要执行的项目以及运行环境 触发器可以支持2种方式:interval 间隔多久触发和 cron 表达式定时执行…...
安卓文件资源中,一个字串包含引用其他字串的写法
具体范例: <string name"product_name" translatable"false">Miscope</string><string name"app_name">string/product_name for USB Camera</string> 注意要先定义再引用。...
解决:谷歌浏览器访问http时,自动转https访问的问题
问题背景:某个系统网站,之前一直用https域名访问,现在改成http域名后,用http访问,谷歌浏览器会自动跳转到https。 解决方法: 在浏览器中输入网址:chrome://net-internals/#hsts -》 在“Delete…...
MQTT协议和边缘计算
1.基本概念 MQTT是基于TCP/IP协议栈构建的异步通信消息协议,是一种轻量级的发布、订阅信息传输协议。可以在不可靠的网络环境中进行扩展,适用于设备硬件存储空间或网络带宽有限的场景。使用MQTT协议,消息发送者与接收者不受时间和空间的限制…...
Redis(04)| 数据结构-压缩列表
压缩列表的最大特点,就是它被设计成一种内存紧凑型的数据结构,占用一块连续的内存空间,不仅可以利用 CPU 缓存,而且会针对不同长度的数据,进行相应编码,这种方法可以有效地节省内存开销。 但是,…...
516 最长回文子序列(区间DP)(灵神笔记)
题目 最长回文子序列 给你一个字符串 s ,找出其中最长的回文子序列,并返回该序列的长度。 子序列定义为:不改变剩余字符顺序的情况下,删除某些字符或者不删除任何字符形成的一个序列。 示例 1: 输入:s …...
Kafka - 异步/同步发送API
文章目录 异步发送普通异步发送异步发送流程Code 带回调函数的异步发送带回调函数的异步发送流程Code 同步发送API 异步发送 普通异步发送 需求:创建Kafka生产者,采用异步的方式发送到Kafka broker 异步发送流程 Code <!-- https://mvnrepository…...
嵌套for循环在外层循环和内层循环中使用两个Executors.newCachedThreadPool缓存线程池执行操作
1. 首先,我们需要创建两个ExecutorService对象,这两个对象将作为我们的缓存线程池。 2. 然后,我们使用嵌套的for循环来执行我们的操作。在每个外层循环中,我们将创建一个新的任务并提交给外层线程池。在这个任务中,我…...
CTF show Web 红包题第六弹
提示 1.不是SQL注入 2.需要找关键源码 思路 进入页面发现是一个登录框,很难让人不联想到SQL注入,但提示都说了不是SQL注入,所以就不往这方面想了 先查看一下网页源码,发现一段JavaScript代码,有一个关键类ctfs…...
CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型
CVPR 2025 | MIMO:支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题:MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者:Yanyuan Chen, Dexuan Xu, Yu Hu…...
IGP(Interior Gateway Protocol,内部网关协议)
IGP(Interior Gateway Protocol,内部网关协议) 是一种用于在一个自治系统(AS)内部传递路由信息的路由协议,主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...
python爬虫:Newspaper3k 的详细使用(好用的新闻网站文章抓取和解析的Python库)
更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 一、Newspaper3k 概述1.1 Newspaper3k 介绍1.2 主要功能1.3 典型应用场景1.4 安装二、基本用法2.2 提取单篇文章的内容2.2 处理多篇文档三、高级选项3.1 自定义配置3.2 分析文章情感四、实战案例4.1 构建新闻摘要聚合器…...
Rust 异步编程
Rust 异步编程 引言 Rust 是一种系统编程语言,以其高性能、安全性以及零成本抽象而著称。在多核处理器成为主流的今天,异步编程成为了一种提高应用性能、优化资源利用的有效手段。本文将深入探讨 Rust 异步编程的核心概念、常用库以及最佳实践。 异步编程基础 什么是异步…...
实现弹窗随键盘上移居中
实现弹窗随键盘上移的核心思路 在Android中,可以通过监听键盘的显示和隐藏事件,动态调整弹窗的位置。关键点在于获取键盘高度,并计算剩余屏幕空间以重新定位弹窗。 // 在Activity或Fragment中设置键盘监听 val rootView findViewById<V…...
ip子接口配置及删除
配置永久生效的子接口,2个IP 都可以登录你这一台服务器。重启不失效。 永久的 [应用] vi /etc/sysconfig/network-scripts/ifcfg-eth0修改文件内内容 TYPE"Ethernet" BOOTPROTO"none" NAME"eth0" DEVICE"eth0" ONBOOT&q…...
docker 部署发现spring.profiles.active 问题
报错: org.springframework.boot.context.config.InvalidConfigDataPropertyException: Property spring.profiles.active imported from location class path resource [application-test.yml] is invalid in a profile specific resource [origin: class path re…...
HashMap中的put方法执行流程(流程图)
1 put操作整体流程 HashMap 的 put 操作是其最核心的功能之一。在 JDK 1.8 及以后版本中,其主要逻辑封装在 putVal 这个内部方法中。整个过程大致如下: 初始判断与哈希计算: 首先,putVal 方法会检查当前的 table(也就…...
安宝特方案丨船舶智造的“AR+AI+作业标准化管理解决方案”(装配)
船舶制造装配管理现状:装配工作依赖人工经验,装配工人凭借长期实践积累的操作技巧完成零部件组装。企业通常制定了装配作业指导书,但在实际执行中,工人对指导书的理解和遵循程度参差不齐。 船舶装配过程中的挑战与需求 挑战 (1…...
