Actuatorspring boot项目中非常强大一个功能,有助于对应用程序进行监视和管理,通过 restful api请求来监管、审计、收集应用的运行情况,针对微服务而言它是必不可少的一个环节。

spring 2.x actuator相对于spring 1.x actuator做了较大的改变。

如何做自己的服务监控?spring boot 1.x服务监控揭秘

****提供了更多的endpoint管理

ID Description Enabled by default

auditevents

Exposes audit events information for the current application.

Yes

beans

Displays a complete list of all the Spring beans in your application.

Yes

caches

Exposes available caches.

Yes

conditions

Shows the conditions that were evaluated on configuration and auto-configuration classes and the reasons why they did or did not match.

Yes

configprops

Displays a collated list of all @ConfigurationProperties.

Yes

env

Exposes properties from Spring’s ConfigurableEnvironment.

Yes

flyway

Shows any Flyway database migrations that have been applied.

Yes

health

Shows application health information.

Yes

httptrace

Displays HTTP trace information (by default, the last 100 HTTP request-response exchanges).

Yes

info

Displays arbitrary application info.

Yes

integrationgraph

Shows the Spring Integration graph.

Yes

loggers

Shows and modifies the configuration of loggers in the application.

Yes

liquibase

Shows any Liquibase database migrations that have been applied.

Yes

metrics

Shows ‘metrics’ information for the current application.

Yes

mappings

Displays a collated list of all @RequestMapping paths.

Yes

scheduledtasks

Displays the scheduled tasks in your application.

Yes

sessions

Allows retrieval and deletion of user sessions from a Spring Session-backed session store. Not available when using Spring Session’s support for reactive web applications.

Yes

shutdown

Lets the application be gracefully shutdown.

No

threaddump

Performs a thread dump.

Yes

If your application is a web application (Spring MVC, Spring WebFlux, or Jersey), you can use the following additional endpoints:

ID Description Enabled by default

heapdump

Returns an hprof heap dump file.

Yes

jolokia

Exposes JMX beans over HTTP (when Jolokia is on the classpath, not available for WebFlux).

Yes

logfile

Returns the contents of the logfile (if logging.file or logging.path properties have been set). Supports the use of the HTTP Range header to retrieve part of the log file’s content.

Yes

prometheus

Exposes metrics in a format that can be scraped by a Prometheus server.

Yes

********更多的metrics

  • JVM metrics, report utilization of:

    • Various memory and buffer pools
    • Statistics related to garbage collection
    • Threads utilization
    • Number of classes loaded/unloaded
  • CPU metrics
  • File descriptor metrics
  • Kafka consumer metrics
  • Log4j2 metrics: record the number of events logged to Log4j2 at each level
  • Logback metrics: record the number of events logged to Logback at each level
  • Uptime metrics: report a gauge for uptime and a fixed gauge representing the application’s absolute start time
  • Tomcat metrics
  • Spring Integration metrics

*********内部实现也发生了较大的变化,使用micrometer第三方工具来完成metric的实现。下面我们就亲自看看吧!

1.准备源码

https://github.com/tjanusz-personal/springbootrestdemo/tree/master/src/main/java/com/demo/springbootrestdemo

2.导入并启动项目

( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.0.4.RELEASE) 2019-01-17 11:20:39.076 INFO 5180 --- [ main] c.d.s.SpringbootrestdemoApplication : Starting SpringbootrestdemoApplication on DESKTOP-405G2C8 with PID 5180 (E:\document\springbootrestdemo\build\classes\java\main started by dell in E:\document\springbootrestdemo)
2019-01-17 11:20:39.080 INFO 5180 --- [ main] c.d.s.SpringbootrestdemoApplication : No active profile set, falling back to default profiles: default
2019-01-17 11:20:39.147 INFO 5180 --- [ main] ConfigServletWebServerApplicationContext : Refreshing org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@6f01b95f: startup date [Thu Jan 17 11:20:39 CST 2019]; root of context hierarchy
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by org.springframework.cglib.core.ReflectUtils$1 (file:/D:/gradle/caches/modules-2/files-2.1/org.springframework/spring-core/5.0.8.RELEASE/dc39c49e3246cdf73d3786ac41119140aed3fa08/spring-core-5.0.8.RELEASE.jar) to method java.lang.ClassLoader.defineClass(java.lang.Stri
ng,byte[],int,int,java.security.ProtectionDomain)
WARNING: Please consider reporting this to the maintainers of org.springframework.cglib.core.ReflectUtils$1
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
2019-01-17 11:20:40.341 INFO 5180 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.hateoas.config.HateoasConfiguration' of type [org.springframework.hateoas.config.HateoasConfiguration$$EnhancerBySpringCGLIB$$ecf2a812] is not eligible for getting processed by a
ll BeanPostProcessors (for example: not eligible for auto-proxying)
2019-01-17 11:20:40.982 INFO 5180 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
2019-01-17 11:20:41.015 INFO 5180 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2019-01-17 11:20:41.016 INFO 5180 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/8.5.32
2019-01-17 11:20:41.029 INFO 5180 --- [ost-startStop-1] o.a.catalina.core.AprLifecycleListener : The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: [D:\software\jdk11\bin;C:\Windows\Sun\Java\bin;C:\Windows\sys
tem32;C:\Windows;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Windows\System32\OpenSSH\;D:\software\jdk11\bin;D:\software\TortoiseGit\bin;D:\software\Git\cmd;D:\software\apache-maven-3.5.4\bin;D:\software\gradle-4.10.2\bin;D:\software\go\bin;D:\s
oftware\ant\bin;D:\software\anaconda;D:\software\anaconda\Scripts;D:\software\anaconda\Library\bin;C:\Users\dell\AppData\Local\Microsoft\WindowsApps;;.]
2019-01-17 11:20:41.162 INFO 5180 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2019-01-17 11:20:41.168 INFO 5180 --- [ost-startStop-1] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 2035 ms
2019-01-17 11:20:41.832 INFO 5180 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'characterEncodingFilter' to: [/*]
2019-01-17 11:20:41.832 INFO 5180 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'webMvcMetricsFilter' to: [/*]
2019-01-17 11:20:41.832 INFO 5180 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'httpTraceFilter' to: [/*]
2019-01-17 11:20:41.833 INFO 5180 --- [ost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean : Servlet dispatcherServlet mapped to [/]
2019-01-17 11:20:41.960 INFO 5180 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/saveUrl],methods=[POST],consumes=[application/json;charset=UTF-8 || application/x-www-form-urlencoded],produces=[application/json;charset=UTF-8 || application/xml]}" onto public com.demo.spring
bootrestdemo.domain.response.SaveUrlResponse com.demo.springbootrestdemo.web.DemoController.saveUrl(com.demo.springbootrestdemo.domain.request.SaveUrlRequest,java.lang.String,java.lang.String)
2019-01-17 11:20:41.961 INFO 5180 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/alive],methods=[GET]}" onto public com.demo.springbootrestdemo.domain.response.DemoPingResponse com.demo.springbootrestdemo.web.DemoController.alive()
2019-01-17 11:20:41.964 INFO 5180 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error],produces=[text/html]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController.errorHtml(javax.servlet.http
.HttpServletRequest,javax.servlet.http.HttpServletResponse)
2019-01-17 11:20:41.964 INFO 5180 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error]}" onto public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController.err
or(javax.servlet.http.HttpServletRequest)
2019-01-17 11:20:42.038 INFO 5180 --- [ main] s.w.s.m.m.a.RequestMappingHandlerAdapter : Looking for @ControllerAdvice: org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@6f01b95f: startup date [Thu Jan 17 11:20:39 CST 2019]; root of context hierar
chy
2019-01-17 11:20:42.087 INFO 5180 --- [ main] .m.m.a.ExceptionHandlerExceptionResolver : Detected @ExceptionHandler methods in restResponseEntityExceptionHandler
2019-01-17 11:20:42.529 INFO 5180 --- [ main] o.s.b.a.e.web.EndpointLinksResolver : Exposing 14 endpoint(s) beneath base path '/actuator'
2019-01-17 11:20:42.538 INFO 5180 --- [ main] s.b.a.e.w.s.WebMvcEndpointHandlerMapping : Mapped "{[/actuator/auditevents],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.web.serv
let.AbstractWebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map<java.lang.String, java.lang.String>)
2019-01-17 11:20:42.539 INFO 5180 --- [ main] s.b.a.e.w.s.WebMvcEndpointHandlerMapping : Mapped "{[/actuator/beans],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.web.servlet.Ab
stractWebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map<java.lang.String, java.lang.String>)
2019-01-17 11:20:42.539 INFO 5180 --- [ main] s.b.a.e.w.s.WebMvcEndpointHandlerMapping : Mapped "{[/actuator/health],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.web.servlet.A
bstractWebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map<java.lang.String, java.lang.String>)
2019-01-17 11:20:42.540 INFO 5180 --- [ main] s.b.a.e.w.s.WebMvcEndpointHandlerMapping : Mapped "{[/actuator/conditions],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.web.servl
et.AbstractWebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map<java.lang.String, java.lang.String>)
2019-01-17 11:20:42.540 INFO 5180 --- [ main] s.b.a.e.w.s.WebMvcEndpointHandlerMapping : Mapped "{[/actuator/configprops],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.web.serv
let.AbstractWebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map<java.lang.String, java.lang.String>)
2019-01-17 11:20:42.540 INFO 5180 --- [ main] s.b.a.e.w.s.WebMvcEndpointHandlerMapping : Mapped "{[/actuator/env/{toMatch}],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.web.se
rvlet.AbstractWebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map<java.lang.String, java.lang.String>)
2019-01-17 11:20:42.541 INFO 5180 --- [ main] s.b.a.e.w.s.WebMvcEndpointHandlerMapping : Mapped "{[/actuator/env],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.web.servlet.Abst
ractWebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map<java.lang.String, java.lang.String>)
2019-01-17 11:20:42.541 INFO 5180 --- [ main] s.b.a.e.w.s.WebMvcEndpointHandlerMapping : Mapped "{[/actuator/info],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.web.servlet.Abs
tractWebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map<java.lang.String, java.lang.String>)
2019-01-17 11:20:42.541 INFO 5180 --- [ main] s.b.a.e.w.s.WebMvcEndpointHandlerMapping : Mapped "{[/actuator/loggers/{name}],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.web.s
ervlet.AbstractWebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map<java.lang.String, java.lang.String>)
2019-01-17 11:20:42.542 INFO 5180 --- [ main] s.b.a.e.w.s.WebMvcEndpointHandlerMapping : Mapped "{[/actuator/loggers/{name}],methods=[POST],consumes=[application/vnd.spring-boot.actuator.v2+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.web.
servlet.AbstractWebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map<java.lang.String, java.lang.String>)
2019-01-17 11:20:42.542 INFO 5180 --- [ main] s.b.a.e.w.s.WebMvcEndpointHandlerMapping : Mapped "{[/actuator/loggers],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.web.servlet.
AbstractWebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map<java.lang.String, java.lang.String>)
2019-01-17 11:20:42.543 INFO 5180 --- [ main] s.b.a.e.w.s.WebMvcEndpointHandlerMapping : Mapped "{[/actuator/heapdump],methods=[GET],produces=[application/octet-stream]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.web.servlet.AbstractWebMvcEndpointHandlerMapping$Op
erationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map<java.lang.String, java.lang.String>)
2019-01-17 11:20:42.543 INFO 5180 --- [ main] s.b.a.e.w.s.WebMvcEndpointHandlerMapping : Mapped "{[/actuator/threaddump],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.web.servl
et.AbstractWebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map<java.lang.String, java.lang.String>)
2019-01-17 11:20:42.543 INFO 5180 --- [ main] s.b.a.e.w.s.WebMvcEndpointHandlerMapping : Mapped "{[/actuator/metrics],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.web.servlet.
AbstractWebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map<java.lang.String, java.lang.String>)
2019-01-17 11:20:42.544 INFO 5180 --- [ main] s.b.a.e.w.s.WebMvcEndpointHandlerMapping : Mapped "{[/actuator/metrics/{requiredMetricName}],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.
endpoint.web.servlet.AbstractWebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map<java.lang.String, java.lang.String>)
2019-01-17 11:20:42.544 INFO 5180 --- [ main] s.b.a.e.w.s.WebMvcEndpointHandlerMapping : Mapped "{[/actuator/scheduledtasks],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.web.s
ervlet.AbstractWebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map<java.lang.String, java.lang.String>)
2019-01-17 11:20:42.544 INFO 5180 --- [ main] s.b.a.e.w.s.WebMvcEndpointHandlerMapping : Mapped "{[/actuator/httptrace],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.web.servle
t.AbstractWebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map<java.lang.String, java.lang.String>)
2019-01-17 11:20:42.545 INFO 5180 --- [ main] s.b.a.e.w.s.WebMvcEndpointHandlerMapping : Mapped "{[/actuator/mappings],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.web.servlet
.AbstractWebMvcEndpointHandlerMapping$OperationHandler.handle(javax.servlet.http.HttpServletRequest,java.util.Map<java.lang.String, java.lang.String>)
2019-01-17 11:20:42.546 INFO 5180 --- [ main] s.b.a.e.w.s.WebMvcEndpointHandlerMapping : Mapped "{[/actuator],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" onto protected java.util.Map<java.lang.String, java.util.Map<java.lang.String, org.springfr
amework.boot.actuate.endpoint.web.Link>> org.springframework.boot.actuate.endpoint.web.servlet.WebMvcEndpointHandlerMapping.links(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)
2019-01-17 11:20:42.590 INFO 5180 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Registering beans for JMX exposure on startup
2019-01-17 11:20:42.641 INFO 5180 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
2019-01-17 11:20:42.648 INFO 5180 --- [ main] c.d.s.SpringbootrestdemoApplication : Started SpringbootrestdemoApplication in 4.008 seconds (JVM running for 4.517)
<=========----> 75% EXECUTING [25s]
> :bootRun

3.获取EndPoint

3.0 来源

        "webEndpointServletHandlerMapping": {
"aliases": [ ],
"scope": "singleton",
"type": "org.springframework.boot.actuate.endpoint.web.servlet.WebMvcEndpointHandlerMapping",
"resource": "class path resource [org/springframework/boot/actuate/autoconfigure/endpoint/web/servlet/WebMvcEndpointManagementContextConfiguration.class]",
"dependencies": [
"webEndpointDiscoverer",
"servletEndpointDiscoverer",
"controllerEndpointDiscoverer",
"endpointMediaTypes",
"management.endpoints.web.cors-org.springframework.boot.actuate.autoconfigure.endpoint.web.CorsEndpointProperties",
"management.endpoints.web-org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties"
]
}

spring.factories定义了

org.springframework.boot.actuate.autoconfigure.web.ManagementContextConfiguration=\
org.springframework.boot.actuate.autoconfigure.endpoint.web.ServletEndpointManagementContextConfiguration,\
org.springframework.boot.actuate.autoconfigure.endpoint.web.reactive.WebFluxEndpointManagementContextConfiguration,\
org.springframework.boot.actuate.autoconfigure.endpoint.web.servlet.WebMvcEndpointManagementContextConfiguration,\
org.springframework.boot.actuate.autoconfigure.endpoint.web.jersey.JerseyWebEndpointManagementContextConfiguration,\
org.springframework.boot.actuate.autoconfigure.web.jersey.JerseyManagementChildContextConfiguration,\
org.springframework.boot.actuate.autoconfigure.web.reactive.ReactiveManagementChildContextConfiguration,\
org.springframework.boot.actuate.autoconfigure.web.servlet.ServletManagementChildContextConfiguration,\
org.springframework.boot.actuate.autoconfigure.web.servlet.WebMvcEndpointChildContextConfiguration

3.1 映射

    @Bean
@ConditionalOnMissingBean
public WebMvcEndpointHandlerMapping webEndpointServletHandlerMapping(
WebEndpointsSupplier webEndpointsSupplier,
ServletEndpointsSupplier servletEndpointsSupplier,
ControllerEndpointsSupplier controllerEndpointsSupplier,
EndpointMediaTypes endpointMediaTypes, CorsEndpointProperties corsProperties,
WebEndpointProperties webEndpointProperties) {
List<ExposableEndpoint<?>> allEndpoints = new ArrayList<>();
Collection<ExposableWebEndpoint> webEndpoints = webEndpointsSupplier
.getEndpoints();
allEndpoints.addAll(webEndpoints);
allEndpoints.addAll(servletEndpointsSupplier.getEndpoints());
allEndpoints.addAll(controllerEndpointsSupplier.getEndpoints());
EndpointMapping endpointMapping = new EndpointMapping(
webEndpointProperties.getBasePath());
return new WebMvcEndpointHandlerMapping(endpointMapping, webEndpoints,
endpointMediaTypes, corsProperties.toCorsConfiguration(),
new EndpointLinksResolver(allEndpoints,
webEndpointProperties.getBasePath()));
}

3.2 获取EndPoint

3.2.1 EndPoint定义

/**
* Identifies a type as being an actuator endpoint that provides information about the
* running application. Endpoints can be exposed over a variety of technologies including
* JMX and HTTP.
* <p>
* Most {@code @Endpoint} classes will declare one or more
* {@link ReadOperation @ReadOperation}, {@link WriteOperation @WriteOperation},
* {@link DeleteOperation @DeleteOperation} annotated methods which will be automatically
* adapted to the exposing technology (JMX, Spring MVC, Spring WebFlux, Jersey etc.).
* <p>
* {@code @Endpoint} represents the lowest common denominator for endpoints and
* intentionally limits the sorts of operation methods that may be defined in order to
* support the broadest possible range of exposure technologies. If you need deeper
* support for a specific technology you can either write an endpoint that is
* {@link FilteredEndpoint filtered} to a certain technology, or provide
* {@link EndpointExtension extension} for the broader endpoint.
*
* @author Andy Wilkinson
* @author Phillip Webb
* @since 2.0.0
* @see EndpointExtension
* @see FilteredEndpoint
* @see EndpointDiscoverer
*/

使用了@Endpoint注解的类

3.2.2 获取所有的EndPoint

    @Override
public final Collection<E> getEndpoints() {
if (this.endpoints == null) {
this.endpoints = discoverEndpoints();
}
return this.endpoints;
} private Collection<E> discoverEndpoints() {
Collection<EndpointBean> endpointBeans = createEndpointBeans();
addExtensionBeans(endpointBeans);
return convertToEndpoints(endpointBeans);
} private Collection<EndpointBean> createEndpointBeans() {
Map<EndpointId, EndpointBean> byId = new LinkedHashMap<>();
String[] beanNames = BeanFactoryUtils.beanNamesForAnnotationIncludingAncestors(
this.applicationContext, Endpoint.class);
for (String beanName : beanNames) {
if (!ScopedProxyUtils.isScopedTarget(beanName)) {
EndpointBean endpointBean = createEndpointBean(beanName);
EndpointBean previous = byId.putIfAbsent(endpointBean.getId(),
endpointBean);
Assert.state(previous == null,
() -> "Found two endpoints with the id '" + endpointBean.getId()
+ "': '" + endpointBean.getBeanName() + "' and '"
+ previous.getBeanName() + "'");
}
}
return byId.values();
} private EndpointBean createEndpointBean(String beanName) {
Object bean = this.applicationContext.getBean(beanName);
return new EndpointBean(beanName, bean);
} private void addExtensionBeans(Collection<EndpointBean> endpointBeans) {
Map<EndpointId, EndpointBean> byId = endpointBeans.stream()
.collect(Collectors.toMap(EndpointBean::getId, Function.identity()));
String[] beanNames = BeanFactoryUtils.beanNamesForAnnotationIncludingAncestors(
this.applicationContext, EndpointExtension.class);
for (String beanName : beanNames) {
ExtensionBean extensionBean = createExtensionBean(beanName);
EndpointBean endpointBean = byId.get(extensionBean.getEndpointId());
Assert.state(endpointBean != null,
() -> ("Invalid extension '" + extensionBean.getBeanName()
+ "': no endpoint found with id '"
+ extensionBean.getEndpointId() + "'"));
addExtensionBean(endpointBean, extensionBean);
}
}

3.3 WebMvcEndpointHandlerMapping

3.3.0 spring mvc的流程复习

其中:

第2步获取HandlerMapping,其层次结构

其中RequestMappingHandlerMapping用来处理@RequestMapping注解

    private RequestMappingInfo createRequestMappingInfo(AnnotatedElement element) {
RequestMapping requestMapping = AnnotatedElementUtils.findMergedAnnotation(element, RequestMapping.class);
RequestCondition<?> condition = (element instanceof Class ?
getCustomTypeCondition((Class<?>) element) : getCustomMethodCondition((Method) element));
return (requestMapping != null ? createRequestMappingInfo(requestMapping, condition) : null);
}

第3步获取HandlerAdapter,其层次结构

默认handlerMapping和handlerAdapter定义在DispatcherServlet.properties

org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,\
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping org.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,\
org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter

3.3.1 获取WebMvcEndpointHandlerMapping

    /**
* Creates a new {@code WebMvcEndpointHandlerMapping} instance that provides mappings
* for the given endpoints.
* @param endpointMapping the base mapping for all endpoints
* @param endpoints the web endpoints
* @param endpointMediaTypes media types consumed and produced by the endpoints
* @param corsConfiguration the CORS configuration for the endpoints or {@code null}
* @param linksResolver resolver for determining links to available endpoints
*/
public WebMvcEndpointHandlerMapping(EndpointMapping endpointMapping,
Collection<ExposableWebEndpoint> endpoints,
EndpointMediaTypes endpointMediaTypes, CorsConfiguration corsConfiguration,
EndpointLinksResolver linksResolver) {
super(endpointMapping, endpoints, endpointMediaTypes, corsConfiguration);
this.linksResolver = linksResolver;
setOrder(-100);
}

父类实现了initHandlerMethods()

    @Override
protected void initHandlerMethods() {
for (ExposableWebEndpoint endpoint : this.endpoints) {
for (WebOperation operation : endpoint.getOperations()) {
registerMappingForOperation(endpoint, operation);
}
}
if (StringUtils.hasText(this.endpointMapping.getPath())) {
registerLinksMapping();
}
}

将endpoint的Operation映射到Method级别,类似于@RequestMapping

    private void registerMappingForOperation(ExposableWebEndpoint endpoint,
WebOperation operation) {
ServletWebOperation servletWebOperation = wrapServletWebOperation(endpoint,
operation, new ServletWebOperationAdapter(operation));
registerMapping(createRequestMappingInfo(operation),
new OperationHandler(servletWebOperation), this.handleMethod);
} /**
* Hook point that allows subclasses to wrap the {@link ServletWebOperation} before
* it's called. Allows additional features, such as security, to be added.
* @param endpoint the source endpoint
* @param operation the source operation
* @param servletWebOperation the servlet web operation to wrap
* @return a wrapped servlet web operation
*/
protected ServletWebOperation wrapServletWebOperation(ExposableWebEndpoint endpoint,
WebOperation operation, ServletWebOperation servletWebOperation) {
return servletWebOperation;
} private RequestMappingInfo createRequestMappingInfo(WebOperation operation) {
WebOperationRequestPredicate predicate = operation.getRequestPredicate();
PatternsRequestCondition patterns = patternsRequestConditionForPattern(
predicate.getPath());
RequestMethodsRequestCondition methods = new RequestMethodsRequestCondition(
RequestMethod.valueOf(predicate.getHttpMethod().name()));
ConsumesRequestCondition consumes = new ConsumesRequestCondition(
StringUtils.toStringArray(predicate.getConsumes()));
ProducesRequestCondition produces = new ProducesRequestCondition(
StringUtils.toStringArray(predicate.getProduces()));
return new RequestMappingInfo(null, patterns, methods, null, null, consumes,
produces, null);
}

3.3.2 获取ServletWebOperationAdapter

AbstractWebMvcEndpointHandlerMapping$OperationHandler.handle

        @Override
public Object handle(HttpServletRequest request,
@RequestBody(required = false) Map<String, String> body) {
Map<String, Object> arguments = getArguments(request, body);
try {
return handleResult(
this.operation.invoke(new InvocationContext(
new ServletSecurityContext(request), arguments)),
HttpMethod.valueOf(request.getMethod()));
}
catch (InvalidEndpointRequestException ex) {
throw new BadOperationRequestException(ex.getReason());
}
}

4.触发机制

If you add a @Bean annotated with @Endpoint, any methods annotated with @ReadOperation@WriteOperation, or @DeleteOperation are automatically exposed over JMX and, in a web application, over HTTP as well. Endpoints can be exposed over HTTP using Jersey, Spring MVC, or Spring WebFlux.

if you need access to web-framework-specific functionality, you can implement Servlet or Spring @Controller and @RestController endpoints at the cost of them not being available over JMX or when using a different web framework.

EndpointDiscoverer

    @Override
public final Collection<E> getEndpoints() {
if (this.endpoints == null) {
this.endpoints = discoverEndpoints();
}
return this.endpoints;
} private Collection<E> discoverEndpoints() {
Collection<EndpointBean> endpointBeans = createEndpointBeans();
addExtensionBeans(endpointBeans);
return convertToEndpoints(endpointBeans);
}

调用 @ReadOperation@WriteOperation, or @DeleteOperation方法

    private void addOperations(MultiValueMap<OperationKey, O> indexed, EndpointId id,
Object target, boolean replaceLast) {
Set<OperationKey> replacedLast = new HashSet<>();
Collection<O> operations = this.operationsFactory.createOperations(id, target);
for (O operation : operations) {
OperationKey key = createOperationKey(operation);
O last = getLast(indexed.get(key));
if (replaceLast && replacedLast.add(key) && last != null) {
indexed.get(key).remove(last);
}
indexed.add(key, operation);
}
}

其中DiscoveredOperationsFactory定义了@ReadOperation@WriteOperation, or @DeleteOperation方法

    private static final Map<OperationType, Class<? extends Annotation>> OPERATION_TYPES;

    static {
Map<OperationType, Class<? extends Annotation>> operationTypes = new EnumMap<>(
OperationType.class);
operationTypes.put(OperationType.READ, ReadOperation.class);
operationTypes.put(OperationType.WRITE, WriteOperation.class);
operationTypes.put(OperationType.DELETE, DeleteOperation.class);
OPERATION_TYPES = Collections.unmodifiableMap(operationTypes);
} private final ParameterValueMapper parameterValueMapper; private final Collection<OperationInvokerAdvisor> invokerAdvisors; DiscoveredOperationsFactory(ParameterValueMapper parameterValueMapper,
Collection<OperationInvokerAdvisor> invokerAdvisors) {
this.parameterValueMapper = parameterValueMapper;
this.invokerAdvisors = invokerAdvisors;
} public Collection<O> createOperations(EndpointId id, Object target) {
return MethodIntrospector.selectMethods(target.getClass(),
(MetadataLookup<O>) (method) -> createOperation(id, target, method))
.values();
} private O createOperation(EndpointId endpointId, Object target, Method method) {
return OPERATION_TYPES.entrySet().stream()
.map((entry) -> createOperation(endpointId, target, method,
entry.getKey(), entry.getValue()))
.filter(Objects::nonNull).findFirst().orElse(null);
}

总结:

1.若一个Bean在类上使用@Endpoint注解,并且在方法上使用@ReadOperation@WriteOperation, or @DeleteOperation注解,那么自动可以使用jmx或者http访问,http提供服务的可以是Jersey, Spring MVC或者Spring WebFlux.

2.http提供服务的基本机制

2.1 使用HandlerMapping映射请求
2.2 使用HandlerAdapter(自定义)聚合EndPoint,并代理EndPoint的请求。

参考文献

【1】https://terasolunaorg.github.io/guideline/1.0.x/en/Overview/SpringMVCOverview.html

【2】https://docs.spring.io/spring-boot/docs/2.1.2.RELEASE/reference/htmlsingle/#production-ready-enabling

如何做自己的服务监控?spring boot 2.x服务监控揭秘的更多相关文章

  1. SpringCloud(8)微服务监控Spring Boot Admin

    1.简介 Spring Boot Admin 是一个管理和监控Spring Boot 应用程序的开源软件.Spring Boot Admin 分为 Server 端和 Client 端,Spring ...

  2. Spring Boot (九): 微服务应用监控 Spring Boot Actuator 详解

    1. 引言 在当前的微服务架构方式下,我们会有很多的服务部署在不同的机器上,相互是通过服务调用的方式进行交互,一个完整的业务流程中间会经过很多个微服务的处理和传递,那么,如何能知道每个服务的健康状况就 ...

  3. spring cloud微服务快速教程之(六) 应用监控 spring boot admin

    0-前言 当我们发布了微服务后,我们希望对各个应用的各个运行状况进行一个监控:这个时候spring boot admin,就出场了: spring boot admin:是一个监控和管理spring ...

  4. 构建微服务:Spring boot

    构建微服务:Spring boot 在上篇文章构建微服务:Spring boot 提高篇中简单介绍了一下spring data jpa的基础性使用,这篇文章将更加全面的介绍spring data jp ...

  5. 一文读懂 Spring Boot、微服务架构和大数据治理三者之间的故事

    微服务架构 微服务的诞生并非偶然,它是在互联网高速发展,技术日新月异的变化以及传统架构无法适应快速变化等多重因素的推动下诞生的产物.互联网时代的产品通常有两类特点:需求变化快和用户群体庞大,在这种情况 ...

  6. Spring boot学习1 构建微服务:Spring boot 入门篇

    Spring boot学习1 构建微服务:Spring boot 入门篇 Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程.该框 ...

  7. 一文读懂spring boot 和微服务的关系

    欢迎访问网易云社区,了解更多网易技术产品运营经验. Spring Boot 和微服务没关系, Java 微服务治理框架普遍用的是 Spring Cloud. Spring Boot 产生的背景,是开发 ...

  8. Spring Boot、微服务架构和大数据

    一文读懂 Spring Boot.微服务架构和大数据治理三者之间的故事 https://www.cnblogs.com/ityouknow/p/9034377.html 微服务架构 微服务的诞生并非偶 ...

  9. 【Spring Boot】利用 Spring Boot Admin 进行项目监控管理

    利用 Spring Boot Admin 进行项目监控管理 一.Spring Boot Admin 是什么 Spring Boot Admin (SBA) 是一个社区开源项目,用于管理和监视 Spri ...

随机推荐

  1. ubuntu中运行java程序

    查找jdk rivsidn@rivsidn:~/demo/java$ sudo apt-cache search jdk default-jdk - Standard Java or Java com ...

  2. JS基础-数组的常用方法-冒泡排序

    1.数组  1.关联数组    以数字作为元素下标的数组,就是索引数组.    以字符串作为元素下标的数组,就是关联数组.  2.js的关联数组    ex:在php中       $array=[& ...

  3. 10. Halloween 万圣节

    10. Halloween 万圣节 (1) On October the 31st,across Britain and the USA,thousands of children are dress ...

  4. Codeforces Round #539 (Div. 2) 异或 + dp

    https://codeforces.com/contest/1113/problem/C 题意 一个n个数字的数组a[],求有多少对l,r满足\(sum[l,mid]=sum[mid+1,r]\), ...

  5. Windows激活客户端 已停止工作

    win+r 进入运行 slmgr /ipx 新的sn slmgr /ato

  6. 分享Pos函数(比FastPos还要快)

    ): Integer; ): Integer; 主要用途是搜索字符串中第n个Substr. 经过测试,这2个函数的速度比直接用Pos+Copy快好几倍(如果字符串够长,可能10几倍) 比Pos+Del ...

  7. 背水一战 Windows 10 (87) - 文件系统: 获取文件的属性, 修改文件的属性, 获取文件的缩略图

    [源码下载] 背水一战 Windows 10 (87) - 文件系统: 获取文件的属性, 修改文件的属性, 获取文件的缩略图 作者:webabcd 介绍背水一战 Windows 10 之 文件系统 获 ...

  8. Javascript高级编程学习笔记(13)—— 引用类型(2)Array类型

    除了Object类型之外ECMA中最常用的引用类型可能就是Array类型了 并且ECMA中的数组类型和其他大多数编程语言的数组类型存在着很大的区别 今天就介绍一下JS中的Array的特别之处 区别 1 ...

  9. PHP校验日期格式是否合法

    在后端开发中,我们常常需要校验前端传入参数的合法性,如果是校验日期参数,我们可以通过下面的方法来校验: /** * 校验日期格式是否合法 * @param string $date * @param ...

  10. 第32节:Java中-构造函数,静态方法,继承,封装,多态,包

    构造函数实例 class Cat{ // 设置私有的属性 name private String name; // 设置name的方法 public void setName(String Name) ...