Springboot应用执行器Actuator源码分析

news2024/9/30 11:25:36

文章目录

  • 一、认识Actuator
    • 1、回顾Actuator
    • 2、Actuator重要端点
  • 二、源码分析
    • 1、Endpoint自动装配
      • (1)自动配置入口
      • (2)普通Endpoint自动装配
      • (3)配置Web - Endpoint
      • (4)注册Endpoint为Mvc映射
    • 2、BeansEndpoint自动装配原理
      • (1)自动装配类
      • (2)BeansEndpoint
      • (3)执行结果
    • 3、MappingsEndpoint自动装配原理
      • (1)自动装配类
      • (2)MappingsEndpoint
      • (3)执行结果
    • 4、ShutdownEndpoint自动装配原理
      • (1)自动装配类
      • (2)ShutdownEndpoint

一、认识Actuator

1、回顾Actuator

Actuator是Springboot提供运行时数据交互的规范。
它覆盖应用内心戏、环境配置、度量指标、敏感操作。
交互方式为Http Web或者JMX。

Spring Boot Actuator ——健康检查神器

2、Actuator重要端点

在这里插入图片描述

二、源码分析

1、Endpoint自动装配

(1)自动配置入口

在这里插入图片描述

(2)普通Endpoint自动装配

@AutoConfiguration
@ConditionalOnAvailableEndpoint(endpoint = EnvironmentEndpoint.class) // EnvironmentEndpoint可用
@EnableConfigurationProperties(EnvironmentEndpointProperties.class)// 构建属性配置文件
public class EnvironmentEndpointAutoConfiguration {

	@Bean
	@ConditionalOnMissingBean
	public EnvironmentEndpoint environmentEndpoint(Environment environment, EnvironmentEndpointProperties properties,
			ObjectProvider<SanitizingFunction> sanitizingFunctions) {
		EnvironmentEndpoint endpoint = new EnvironmentEndpoint(environment,
				sanitizingFunctions.orderedStream().collect(Collectors.toList()));
		String[] keysToSanitize = properties.getKeysToSanitize();
		if (keysToSanitize != null) {
			endpoint.setKeysToSanitize(keysToSanitize);
		}
		String[] additionalKeysToSanitize = properties.getAdditionalKeysToSanitize();
		if (additionalKeysToSanitize != null) {
			endpoint.keysToSanitize(additionalKeysToSanitize);
		}
		return endpoint;
	}

	@Bean
	@ConditionalOnMissingBean
	@ConditionalOnBean(EnvironmentEndpoint.class)
	@ConditionalOnAvailableEndpoint(exposure = { EndpointExposure.WEB, EndpointExposure.CLOUD_FOUNDRY })
	public EnvironmentEndpointWebExtension environmentEndpointWebExtension(EnvironmentEndpoint environmentEndpoint) {
		return new EnvironmentEndpointWebExtension(environmentEndpoint);
	}

}

(3)配置Web - Endpoint

通过自动配置类WebEndpointAutoConfiguration进行自动装配。


// org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointAutoConfiguration#webEndpointDiscoverer
@Bean
@ConditionalOnMissingBean(WebEndpointsSupplier.class)
public WebEndpointDiscoverer webEndpointDiscoverer(ParameterValueMapper parameterValueMapper,
		EndpointMediaTypes endpointMediaTypes, ObjectProvider<PathMapper> endpointPathMappers,
		ObjectProvider<OperationInvokerAdvisor> invokerAdvisors,
		ObjectProvider<EndpointFilter<ExposableWebEndpoint>> filters) {
		// 把所有的Web - Endpoint都搜集到
	return new WebEndpointDiscoverer(this.applicationContext, parameterValueMapper, endpointMediaTypes,
			endpointPathMappers.orderedStream().collect(Collectors.toList()),
			invokerAdvisors.orderedStream().collect(Collectors.toList()),
			filters.orderedStream().collect(Collectors.toList()));
}

(4)注册Endpoint为Mvc映射

通过自动配置类WebMvcEndpointManagementContextConfiguration注册Endpoint为Mvc映射。

通过各种方式定义的Endpoint,创建为WebMvcEndpointHandlerMapping,进行Web映射。

// org.springframework.boot.actuate.autoconfigure.endpoint.web.servlet.WebMvcEndpointManagementContextConfiguration#webEndpointServletHandlerMapping
@Bean
@ConditionalOnMissingBean
public WebMvcEndpointHandlerMapping webEndpointServletHandlerMapping(WebEndpointsSupplier webEndpointsSupplier,
		ServletEndpointsSupplier servletEndpointsSupplier, ControllerEndpointsSupplier controllerEndpointsSupplier,
		EndpointMediaTypes endpointMediaTypes, CorsEndpointProperties corsProperties,
		WebEndpointProperties webEndpointProperties, Environment environment) {
	List<ExposableEndpoint<?>> allEndpoints = new ArrayList<>();
	Collection<ExposableWebEndpoint> webEndpoints = webEndpointsSupplier.getEndpoints();
	allEndpoints.addAll(webEndpoints);
	allEndpoints.addAll(servletEndpointsSupplier.getEndpoints());
	allEndpoints.addAll(controllerEndpointsSupplier.getEndpoints());
	String basePath = webEndpointProperties.getBasePath();
	EndpointMapping endpointMapping = new EndpointMapping(basePath);
	boolean shouldRegisterLinksMapping = shouldRegisterLinksMapping(webEndpointProperties, environment, basePath);
	return new WebMvcEndpointHandlerMapping(endpointMapping, webEndpoints, endpointMediaTypes,
			corsProperties.toCorsConfiguration(), new EndpointLinksResolver(allEndpoints, basePath),
			shouldRegisterLinksMapping, WebMvcAutoConfiguration.pathPatternParser);
}

2、BeansEndpoint自动装配原理

(1)自动装配类

@AutoConfiguration
@ConditionalOnAvailableEndpoint(endpoint = BeansEndpoint.class)
public class BeansEndpointAutoConfiguration {

	@Bean
	@ConditionalOnMissingBean
	public BeansEndpoint beansEndpoint(ConfigurableApplicationContext applicationContext) {
		// 创建一个BeansEndpoint
		return new BeansEndpoint(applicationContext);
	}

}

(2)BeansEndpoint

// id就是可以访问的web路径
@Endpoint(id = "beans")
public class BeansEndpoint {
// 读操作
@ReadOperation
public ApplicationBeans beans() {
	Map<String, ContextBeans> contexts = new HashMap<>();
	// 将所有容器都拿出来
	ConfigurableApplicationContext context = this.context;
	while (context != null) {
		// 将Bean都拿出来,封装成一个ContextBeans
		contexts.put(context.getId(), ContextBeans.describing(context));
		context = getConfigurableParent(context);
	}
	// 创建一个ApplicationBeans
	// 返回的信息就会json格式化到响应
	return new ApplicationBeans(contexts);
}
// 返回的对象
public static final class ApplicationBeans {

	private final Map<String, ContextBeans> contexts;

	private ApplicationBeans(Map<String, ContextBeans> contexts) {
		this.contexts = contexts;
	}

	public Map<String, ContextBeans> getContexts() {
		return this.contexts;
	}

}

(3)执行结果

在这里插入图片描述

3、MappingsEndpoint自动装配原理

(1)自动装配类

@AutoConfiguration
@ConditionalOnAvailableEndpoint(endpoint = MappingsEndpoint.class)
public class MappingsEndpointAutoConfiguration {

	// 配置Mapping
	@Bean
	public MappingsEndpoint mappingsEndpoint(ApplicationContext applicationContext,
			ObjectProvider<MappingDescriptionProvider> descriptionProviders) {
		return new MappingsEndpoint(descriptionProviders.orderedStream().collect(Collectors.toList()),
				applicationContext);
	}

	// 后面还有关于Servlet的相关配置,此处就先不看

(2)MappingsEndpoint

// web访问路径
@Endpoint(id = "mappings")
public class MappingsEndpoint {
// org.springframework.boot.actuate.web.mappings.MappingsEndpoint#mappings
@ReadOperation
public ApplicationMappings mappings() {
	ApplicationContext target = this.context;
	Map<String, ContextMappings> contextMappings = new HashMap<>();
	while (target != null) {
		// 查找所有的Mapping
		contextMappings.put(target.getId(), mappingsForContext(target));
		target = target.getParent();
	}
	return new ApplicationMappings(contextMappings);// 返回的信息就会json格式化到响应
}

// org.springframework.boot.actuate.web.mappings.MappingsEndpoint#mappingsForContext
private ContextMappings mappingsForContext(ApplicationContext applicationContext) {
	Map<String, Object> mappings = new HashMap<>();
	this.descriptionProviders.forEach(
			(provider) -> mappings.put(provider.getMappingName(), provider.describeMappings(applicationContext)));
	return new ContextMappings(mappings,
			(applicationContext.getParent() != null) ? applicationContext.getId() : null);
}

在这里插入图片描述

(3)执行结果

在这里插入图片描述
在这里插入图片描述

4、ShutdownEndpoint自动装配原理

(1)自动装配类

@AutoConfiguration
@ConditionalOnAvailableEndpoint(endpoint = ShutdownEndpoint.class)
public class ShutdownEndpointAutoConfiguration {

	@Bean(destroyMethod = "")
	@ConditionalOnMissingBean
	public ShutdownEndpoint shutdownEndpoint() {
		return new ShutdownEndpoint();
	}

}

(2)ShutdownEndpoint

// 默认是不开启的,因为安全性要求极高
@Endpoint(id = "shutdown", enableByDefault = false)
public class ShutdownEndpoint implements ApplicationContextAware {

	private static final Map<String, String> NO_CONTEXT_MESSAGE = Collections
		.unmodifiableMap(Collections.singletonMap("message", "No context to shutdown."));

	private static final Map<String, String> SHUTDOWN_MESSAGE = Collections
		.unmodifiableMap(Collections.singletonMap("message", "Shutting down, bye..."));

	private ConfigurableApplicationContext context;

	// 写操作
	@WriteOperation
	public Map<String, String> shutdown() {
		if (this.context == null) {
			return NO_CONTEXT_MESSAGE; // 返回的信息就会json格式化到响应
		}
		try {
			return SHUTDOWN_MESSAGE;
		}
		finally {
			// 另起一个线程进行shutdown操作,目的是优雅关机。
			Thread thread = new Thread(this::performShutdown);
			thread.setContextClassLoader(getClass().getClassLoader());
			thread.start();
		}
	}

	private void performShutdown() {
		try {
			// 暂停500毫秒
			Thread.sleep(500L);
		}
		catch (InterruptedException ex) {
			Thread.currentThread().interrupt();
		}
		// 执行Spring容器关闭操作
		this.context.close();
	}

	@Override
	public void setApplicationContext(ApplicationContext context) throws BeansException {
		if (context instanceof ConfigurableApplicationContext) {
			this.context = (ConfigurableApplicationContext) context;
		}
	}

}

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

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

相关文章

java面试题之nginx篇

1. 什么是Nginx&#xff1f; Nginx是一个 轻量级/高性能的反向代理Web服务器&#xff0c;他实现非常高效的反向代理、负载平衡&#xff0c;他可以处理2-3万并发连接数&#xff0c;官方监测能支持5万并发&#xff0c;现在中国使用nginx网站用户有很多&#xff0c;例如&#xff…

从零实现一套低代码(保姆级教程)【后端服务】 --- 【23】实现数据库表新增数据以及页面展示

摘要 在上一篇中&#xff0c;我们实现了可视化创建数据库表。并没说怎么对表中的数据进行操作。OK&#xff0c;现在我们来实现相关的内容。 如果说&#xff0c;对于新增数据我们无非有两种入口&#xff1a; 在AppBuilder中&#xff0c;可以通过可视化操作数据在XinBuilder中&…

通过Power automate上传文件到SharePoint

上传文件到SharePoint 背景过程Apps开发准备Flow开发SharePoint数据库测试 背景 我们通常都可以通过一些form表单直接上传文件&#xff0c;但是有些时候我们需要对文件名字等信息做一些处理。这个时候我们就需要将文件的内容json流化&#xff0c;然后在流中还原回来。 过程 …

2-24算法习题总结

贪心算法 409. 最长回文串 题目: 给定一个包含大写字母和小写字母的字符串 s &#xff0c;返回 通过这些字母构造成的 最长的回文串 。 在构造过程中&#xff0c;请注意 区分大小写 。比如 “Aa” 不能当做一个回文字符串。 示例 1: 输入 s "abccccdd"输出 7…

Linux 的交换空间(swap)是什么?有什么用?

目录 swap是什么&#xff1f;swap有什么用&#xff1f;swap使用典型场景如何查看你的系统是否用到交换空间呢&#xff1f;查看系统中swap in/out的情况 swap是什么&#xff1f; swap就是磁盘上的一块区域。它和Windows系统中的交换文件作用类似&#xff0c;但是它是一段连续的…

台阶仪在新材料纳米加工中的优势

台阶仪亚埃级垂直分辨率能够实现纳米级别的测量和分析&#xff0c;仪器具备出色的精确性和稳定性。在纳米加工领域&#xff0c;台阶仪不仅能准确评估材料的表面形貌和结构&#xff0c;同时也为纳米加工过程的控制和优化提供了可靠的依据。利用台阶仪实时观测材料表面的微观变化…

vue_pdf,word,excel,pptx等文件预览

项目背景&#xff1a;vue3elementPlusvite 1.pdf 1.1 iframe预览 #toolbar0 拼接到src后&#xff0c;可隐藏iframe顶部的工具栏 <template><div class"viewPDF.vue"><uploadFile file"getFile" accept".pdf,.PDF" ></up…

系统性能提升70%!华润万家某核心系统数据库升级实践

华润万家是华润集团旗下优秀零售连锁企业&#xff0c;业务覆盖中国内地及香港市场&#xff0c;面对万家众多业务需求和互相关联的业务环境&#xff0c;亟需加强各业务耦合性&#xff0c;以适应线上、线下、物流、财务等各个业务环境的快速发展。 随着信息技术的快速发展和数字化…

ubuntu新建ap热点并分享

测试环境ubuntu16 1.方法1 直接手动新建ap热点 参考https://jingyan.baidu.com/article/ea24bc39b03fc6da62b331f0.html https://jingyan.baidu.com/article/363872ecd8f35d6e4ba16f97.html 亲测&#xff0c;发现电脑如果没有连有线&#xff0c;按照以上步骤并不能生成wifi热…

嵌入式学习 Day 24

1.exec函数族 extern char **environ; int execl(const char *path, const char *arg, ... /* (char *) NULL */); int execlp(const char *file, const char *arg, ... /* (char *) NULL */); int execle(const char *path…

插件废土课:打造属于你的“智能笔记”!

哎呀嘞&#xff0c;亲爱的网页冲浪者们&#xff0c;抓紧浮板&#xff0c;我们要继续在Chrome插件的海浪上翻滚啦&#xff01;上次我们玩了个小把戏&#xff0c;搞了个显示时间的Hello World插件&#xff0c;这次我们要把游戏玩大&#xff0c;准备打造一个能让你在网页上乱涂乱画…

【论文精读】LLaMA1

摘要 以往的LLM&#xff08;Large Languages Models&#xff09;研究都遵从一个假设&#xff0c;即更多的参数将导致更好的性能。但也发现&#xff0c;给定计算预算限制后&#xff0c;最佳性能的模型不是参数最大的&#xff0c;而是数据更多的。对于实际场景&#xff0c;首选的…

Qt QWidget 简约美观的加载动画 第二季

&#x1f603; 第二季来啦 &#x1f603; 简约的加载动画,用于网络查询等耗时操作时给用户的提示. 这是最终效果: 一共只有三个文件,可以直接编译运行 //main.cpp #include "LoadingAnimWidget.h" #include <QApplication> #include <QVBoxLayout> #i…

RabbitMq:RabbitMq消息中的相关处理 ③

一、解耦思想 在 RabbitMQ 在设计的时候&#xff0c;特意让生产者和消费者分离&#xff0c;也就是消息的发布和消息的消费之间是解耦的。 生产者与消费者之间的直连&#xff0c;少了很多的灵活性和策略的制定。还有一种解耦的思想存在。 二、消息的可靠性保证与性能关系 消息的…

APP自动化第一步:Appium环境搭建

一、安装Appium Python client包 1.直接cmd窗口输入pip install Appium-Python-Client 2.要确保安装匹配版本的selenium和appium 使用命令pip install selenium -U 首先进入网盘下载这三个软件的压缩包 二、安装Appium Server 1.双击打开压缩包Appium 2.双击进行安装。 3.点…

卡玛网● 46. 携带研究材料 ● 01背包问题,你该了解这些! 滚动数组 力扣● 416. 分割等和子集

开始背包问题&#xff0c;掌握0-1背包和完全背包即可&#xff0c;注&#xff1a;0-1背包是完全背包的基础。 0-1背包问题&#xff1a;有n件物品和一个最多能背重量为w 的背包。第i件物品的重量是weight[i]&#xff0c;得到的价值是value[i] 。每件物品只能用一次&#xff0c;求…

最短路径——通过Dynamo批量创建行进路线

今天我们来聊聊Revit2020新增的一个功能——布线分析&#xff0c;这个功能还是挺有意思的&#xff0c;只是需要”桌子“以后多开放点API就好了&#xff0c;今天我们就简单的试用一下这个功能。 打开Revit2020我们在分析选项卡下&#xff0c;最右侧可以找到布线分析功能栏&am…

JavaScript事件机制

JavaScript事件机制描述的是事件在DOM里面的传递顺序&#xff0c;以及可以对这些事件做出如何的响应。 DOM事件流存在三个阶段&#xff1a; ①事件捕获阶段(从window对象传导到目标节点)、 ②处于目标阶段(在目标节点上触发)、 ③事件冒泡阶段(从目标节点传导回window对象)。 在…

JVM虚拟机初步了解

各位小伙伴们大家好&#xff0c;欢迎来到这个小扎扎的专栏 总结 | 提效 | 拓展&#xff0c;在这个系列专栏中记录了博主在学习期间总结的大块知识点&#xff1b;以及日常工作中遇到的各种技术点 ┗|&#xff40;O′|┛ &#x1f306; 题目速览 1. JVM的位置2. JVM的体系结构3…

python(ch2)

可变长编码和不可变长编码 可变长编码是指不同字符使用不同数量的字节进行编码。例如&#xff0c;UTF-8 编码中&#xff0c;ASCII 字符使用 1 个字节编码&#xff0c;而其他语言的字符使用 2 个或更多字节编码。 不可变长编码是指所有字符都使用相同数量的字节进行编码。例如…