SpringBoot Actuator、Prometheus 源码分析

1、pom引入jar,配置yml

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
端点如果加载,暴露 ===> 指标

【启动】
spring-boot-starter-actuator
spring-boot-actuator-autoconfigure

spring.factories - WebEndpointAutoConfiguration
WebEndpointDiscoverer
ControllerEndpointDiscoverer
ServletEndpointDiscoverer
PathMappedEndpoints
--- 调用所有 Discoverer getEndpoints
--- createEndpointBeans() @Endpoint
--- isEndpointExposed 是否暴露端点
--- addOperations 生成Operation
spring.factories - WebMvcEndpointManagementContextConfiguration
WebMvcEndpointHandlerMapping
EndpointLinksResolver resolveLinks(String requestUrl)

【访问】
DispatcherServlet doDispatch
RequestMappingHandlerAdapter invokeHandlerMethod
ServletInvocableHandlerMethod invokeAndHandle
===> WebMvcEndpointHandlerMapping EndpointLinksResolver resolveLinks(String requestUrl)

ExposableWebEndpoint Collection<O> getOperations(); ===> Operation 扩展路径
PathMappedEndpoint String getRootPath() ===> /actuator 根路径

AbstractWebMvcEndpointHandlerMapping.ServletWebOperationAdapter handle
HealthEndpointWebExtension health

2、health ===> 健康-可用

1
2
3
4
5
6
7
http://127.0.0.1:18006/actuator/health

DispatcherServlet doDispatch
RequestMappingHandlerAdapter invokeHandlerMethod
ServletInvocableHandlerMethod invokeAndHandle
AbstractWebMvcEndpointHandlerMapping.ServletWebOperationAdapter handle
HealthEndpointWebExtension health

3、集成prometheus 暴露端点

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
PrometheusMetricsExportAutoConfiguration      @ConditionalOnClass(PrometheusMeterRegistry.class)

PrometheusMeterRegistry


-- 默认绑定 ------------------------------
MetricsAutoConfiguration -> MeterRegistryPostProcessor

postProcessAfterInitialization -> PrometheusMeterRegistry Bean 会进入

addBinders(registry); ===> binder.bindTo(registry)
-- Tomcat绑定(项目启动时,监听事件) ------------------------------
TomcatMetricsBinder implements ApplicationListener<ApplicationStartedEvent>
@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);
}

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

4、数据动态化

1
2
3
4
5
6
lambda表达式  ===> TomcatMetrics

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

5、独立端口原理

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
management.server.port=17006   异端口(独享线程池)    ManagementServerPortUtils.ManagementServerPort
同端口,异端口

ManagementContextAutoConfiguration

SameManagementContextConfiguration @ConditionalOnManagementPort(ManagementPortType.SAME)
EnableSameManagementContextConfiguration @EnableManagementContext(ManagementContextType.SAME)

-- 主容器打满,子容器还能继续使用
DifferentManagementContextConfiguration @ConditionalOnManagementPort(ManagementPortType.DIFFERENT)
EnableChildManagementContextConfiguration @EnableManagementContext(ManagementContextType.CHILD)
ServletManagementContextFactory.createManagementContext
registerServletWebServerFactory(parent, child);
determineServletWebServerFactoryClass(parent) --- 确定 Tomcat 、 Jetty 、 Undertow
managementContext.refresh();


-- 异端口,新DispatcherServlet
@EnableManagementContext(ManagementContextType.CHILD) ===> @Import(ManagementContextConfigurationImportSelector.class)

protected List<String> loadFactoryNames() {
return SpringFactoriesLoader.loadFactoryNames(ManagementContextConfiguration.class, this.classLoader);
}

WebMvcEndpointChildContextConfiguration
@Bean(name = DispatcherServletAutoConfiguration.DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)
DispatcherServlet dispatcherServlet() {
DispatcherServlet dispatcherServlet = new DispatcherServlet();
...
return dispatcherServlet;
}