如何做自己的服务监控?spring boot 2.x服务监控揭秘
Actuator
是spring boot
项目中非常强大一个功能,有助于对应用程序进行监视和管理,通过 restful api
请求来监管、审计、收集应用的运行情况,针对微服务而言它是必不可少的一个环节。
spring 2.x actuator相对于spring 1.x actuator做了较大的改变。
如何做自己的服务监控?spring boot 1.x服务监控揭秘
****提供了更多的endpoint管理
ID | Description | Enabled by default |
---|---|---|
|
Exposes audit events information for the current application. |
Yes |
|
Displays a complete list of all the Spring beans in your application. |
Yes |
|
Exposes available caches. |
Yes |
|
Shows the conditions that were evaluated on configuration and auto-configuration classes and the reasons why they did or did not match. |
Yes |
|
Displays a collated list of all |
Yes |
|
Exposes properties from Spring’s |
Yes |
|
Shows any Flyway database migrations that have been applied. |
Yes |
|
Shows application health information. |
Yes |
|
Displays HTTP trace information (by default, the last 100 HTTP request-response exchanges). |
Yes |
|
Displays arbitrary application info. |
Yes |
|
Shows the Spring Integration graph. |
Yes |
|
Shows and modifies the configuration of loggers in the application. |
Yes |
|
Shows any Liquibase database migrations that have been applied. |
Yes |
|
Shows ‘metrics’ information for the current application. |
Yes |
|
Displays a collated list of all |
Yes |
|
Displays the scheduled tasks in your application. |
Yes |
|
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 |
|
Lets the application be gracefully shutdown. |
No |
|
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 |
---|---|---|
|
Returns an |
Yes |
|
Exposes JMX beans over HTTP (when Jolokia is on the classpath, not available for WebFlux). |
Yes |
|
Returns the contents of the logfile (if |
Yes |
|
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服务监控揭秘的更多相关文章
- SpringCloud(8)微服务监控Spring Boot Admin
1.简介 Spring Boot Admin 是一个管理和监控Spring Boot 应用程序的开源软件.Spring Boot Admin 分为 Server 端和 Client 端,Spring ...
- Spring Boot (九): 微服务应用监控 Spring Boot Actuator 详解
1. 引言 在当前的微服务架构方式下,我们会有很多的服务部署在不同的机器上,相互是通过服务调用的方式进行交互,一个完整的业务流程中间会经过很多个微服务的处理和传递,那么,如何能知道每个服务的健康状况就 ...
- spring cloud微服务快速教程之(六) 应用监控 spring boot admin
0-前言 当我们发布了微服务后,我们希望对各个应用的各个运行状况进行一个监控:这个时候spring boot admin,就出场了: spring boot admin:是一个监控和管理spring ...
- 构建微服务:Spring boot
构建微服务:Spring boot 在上篇文章构建微服务:Spring boot 提高篇中简单介绍了一下spring data jpa的基础性使用,这篇文章将更加全面的介绍spring data jp ...
- 一文读懂 Spring Boot、微服务架构和大数据治理三者之间的故事
微服务架构 微服务的诞生并非偶然,它是在互联网高速发展,技术日新月异的变化以及传统架构无法适应快速变化等多重因素的推动下诞生的产物.互联网时代的产品通常有两类特点:需求变化快和用户群体庞大,在这种情况 ...
- Spring boot学习1 构建微服务:Spring boot 入门篇
Spring boot学习1 构建微服务:Spring boot 入门篇 Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程.该框 ...
- 一文读懂spring boot 和微服务的关系
欢迎访问网易云社区,了解更多网易技术产品运营经验. Spring Boot 和微服务没关系, Java 微服务治理框架普遍用的是 Spring Cloud. Spring Boot 产生的背景,是开发 ...
- Spring Boot、微服务架构和大数据
一文读懂 Spring Boot.微服务架构和大数据治理三者之间的故事 https://www.cnblogs.com/ityouknow/p/9034377.html 微服务架构 微服务的诞生并非偶 ...
- 【Spring Boot】利用 Spring Boot Admin 进行项目监控管理
利用 Spring Boot Admin 进行项目监控管理 一.Spring Boot Admin 是什么 Spring Boot Admin (SBA) 是一个社区开源项目,用于管理和监视 Spri ...
随机推荐
- C++中的仿函数
仿函数:实质就是重载了小括号(),通过类,定义一个对象,对象可以被实例化,具有内存可以存储数据,把需要比较的数据事先给到类对象的成员,这样在比较两个值的时候,可以只传入需要被比较的值即可.因为比较的值 ...
- 探索未知种族之osg类生物---呼吸分解之更新循环二
_scene->updateSceneGraph(*_updateVisitor); 我们用了前面4节才刚刚算是完成对DatabasePager::DatabaseThread::run()函数 ...
- 哪些人才适合转行学习UI设计?
最近有很多学员问,怎么才知道自己适不适合学习UI设计,在从事IT教育行业多年以来,也确实碰到好多人咨询这个问题,今天就和大家说下,哪些人才适合转行学习UI设计?(转行必看) 1 平面设计师.网页设计师 ...
- js 定时更改div背景图片
今天遇到一个业务场景,使用js将一个div标签的背景图片定时更换一下. 之前百度了几个,有css+js,也有css3的,不过css3的兼容有问题,之后同事提示,可以使用js直接来更换div的北京图片, ...
- Linux 6上使用UDEV绑定共享存储
1.硬盘的查看方式 [root@cl6-11gr2-rac1 ~]# ls -ltr /dev/sd* brw-rw----. 1 root disk 8, 48 8月 16 13:34 /dev/s ...
- $q的基本用法
angularjs的http是异步的没有同步,一般都会遇到一个场景,会把异步请求的参数作为条件执行下一个函数,之前一直在看其他人的博客理论太多看了很久才看懂 http({ method:'post', ...
- Android -Services 使用简介
Android Services 四大组件之一,主要用于后台长时间运行.没有界面.这里讲解两种services的启动还有AIDL通信方式. 1.startservices a.建立继承services ...
- 检索COM类工厂中CLSID为{10020100-E260-11CF-AE68-00AA004A34D5}的组件时失败,原因是出现以下错误:80040154
{"检索 COM 类工厂中 CLSID 为 {10020100-E260-11CF-AE68-00AA004A34D5} 的组件时失败,原因是出现以下错误: 80040154."} ...
- mac下安装安卓开发环境
对于做ios的人来说,安装安卓开发环境,最好是在mac下安装了,我的mac是10.8.2,64位系统的 安卓开发环境需要下面几个东西: 1 jdk(mac下已经默认有了,可以在命令提示符下输入java ...
- Android 实现手写板技术
Android手写板和涂鸦的功能,代码如下: <LinearLayout xmlns:android="http://schemas.android.com/apk/res/andro ...