如何做自己的服务监控?spring boot 1.x服务监控揭秘
1.準備
? 下載可運行程序:http://www.mkyong.com/spring-boot/spring-boot-hello-world-example-jsp/
? 2.添加服務監控依賴
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId><scope>provided</scope></dependency>3.啟動spring boot項目
console 截圖如下:
4.servlet和filter
? 4.1 使用ServletRegistrationBean注冊dispatcherServlet
/*** A {@link ServletContextInitializer} to register {@link Servlet}s in a Servlet 3.0+* container. Similar to the {@link ServletContext#addServlet(String, Servlet)* registration} features provided by {@link ServletContext} but with a Spring Bean* friendly design.* <p>* The {@link #setServlet(Servlet) servlet} must be specified before calling* {@link #onStartup}. URL mapping can be configured used {@link #setUrlMappings} or* omitted when mapping to '/*' (unless* {@link #ServletRegistrationBean(Servlet, boolean, String...) alwaysMapUrl} is set to* {@code false}). The servlet name will be deduced if not specified.** @param <T> the type of the {@link Servlet} to register* @author Phillip Webb* @since 1.4.0* @see ServletContextInitializer* @see ServletContext#addServlet(String, Servlet)*/總結:類似于ServletContext#addServlet(String, Servlet)
查看所有注冊的bean
http://127.0.0.1:8080/beans
并把返回的json 格式化 視圖查看,在線工具(http://www.bejson.com/jsonviewernew/)
注冊的流程:
spring-boot-autoconfigure模塊spring.facotories的屬性org.springframework.boot.autoconfigure.EnableAutoConfiguration=DispatcherServletAutoConfiguration
@Bean(name = DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME)@ConditionalOnBean(value = DispatcherServlet.class, name = DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)public DispatcherServletRegistrationBean dispatcherServletRegistration(DispatcherServlet dispatcherServlet) {DispatcherServletRegistrationBean registration = new DispatcherServletRegistrationBean(dispatcherServlet, this.webMvcProperties.getServlet().getPath());registration.setName(DEFAULT_DISPATCHER_SERVLET_BEAN_NAME);registration.setLoadOnStartup(this.webMvcProperties.getServlet().getLoadOnStartup());if (this.multipartConfig != null) {registration.setMultipartConfig(this.multipartConfig);}return registration;}4.2 使用FilterRegistrationBean注冊各種filter
/*** A {@link ServletContextInitializer} to register {@link Filter}s in a Servlet 3.0+* container. Similar to the {@link ServletContext#addFilter(String, Filter) registration}* features provided by {@link ServletContext} but with a Spring Bean friendly design.* <p>* The {@link #setFilter(Filter) Filter} must be specified before calling* {@link #onStartup(ServletContext)}. Registrations can be associated with* {@link #setUrlPatterns URL patterns} and/or servlets (either by {@link #setServletNames* name} or via a {@link #setServletRegistrationBeans ServletRegistrationBean}s. When no* URL pattern or servlets are specified the filter will be associated to '/*'. The filter* name will be deduced if not specified.** @param <T> the type of {@link Filter} to register* @author Phillip Webb* @since 1.4.0* @see ServletContextInitializer* @see ServletContext#addFilter(String, Filter)* @see DelegatingFilterProxyRegistrationBean*/總結:類似于ServletContext#addFilter(String, Filter)
?spring-boot-actuator-autoconfigure模塊spring.facotories的屬性org.springframework.boot.autoconfigure.EnableAutoConfiguration=WebMvcMetricsAutoConfiguration,......
5.RequestMappingHandlerAdapter查找controller注解
使用
2019-01-16 09:47:07.715 INFO 8468 --- [ main] s.w.s.m.m.a.RequestMappingHandlerAdapter : Looking for @ControllerAdvice: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@66ac5762: startup date [Wed Jan 16 09:47:06 CST 2019]; root of context hierarchy定義:
/*** An {@link AbstractHandlerMethodAdapter} that supports {@link HandlerMethod}s* with their method argument and return type signature, as defined via* {@code @RequestMapping}.** <p>Support for custom argument and return value types can be added via* {@link #setCustomArgumentResolvers} and {@link #setCustomReturnValueHandlers}.* Or alternatively, to re-configure all argument and return value types,* use {@link #setArgumentResolvers} and {@link #setReturnValueHandlers}.** @author Rossen Stoyanchev* @author Juergen Hoeller* @since 3.1* @see HandlerMethodArgumentResolver* @see HandlerMethodReturnValueHandler*/內部實現源碼
private void initControllerAdviceCache() {if (getApplicationContext() == null) {return;}if (logger.isInfoEnabled()) {logger.info("Looking for @ControllerAdvice: " + getApplicationContext());}List<ControllerAdviceBean> beans = ControllerAdviceBean.findAnnotatedBeans(getApplicationContext());AnnotationAwareOrderComparator.sort(beans);List<Object> requestResponseBodyAdviceBeans = new ArrayList<Object>();for (ControllerAdviceBean bean : beans) {Set<Method> attrMethods = MethodIntrospector.selectMethods(bean.getBeanType(), MODEL_ATTRIBUTE_METHODS);if (!attrMethods.isEmpty()) {this.modelAttributeAdviceCache.put(bean, attrMethods);if (logger.isInfoEnabled()) {logger.info("Detected @ModelAttribute methods in " + bean);}}Set<Method> binderMethods = MethodIntrospector.selectMethods(bean.getBeanType(), INIT_BINDER_METHODS);if (!binderMethods.isEmpty()) {this.initBinderAdviceCache.put(bean, binderMethods);if (logger.isInfoEnabled()) {logger.info("Detected @InitBinder methods in " + bean);}}if (RequestBodyAdvice.class.isAssignableFrom(bean.getBeanType())) {requestResponseBodyAdviceBeans.add(bean);if (logger.isInfoEnabled()) {logger.info("Detected RequestBodyAdvice bean in " + bean);}}if (ResponseBodyAdvice.class.isAssignableFrom(bean.getBeanType())) {requestResponseBodyAdviceBeans.add(bean);if (logger.isInfoEnabled()) {logger.info("Detected ResponseBodyAdvice bean in " + bean);}}}if (!requestResponseBodyAdviceBeans.isEmpty()) {this.requestResponseBodyAdvice.addAll(0, requestResponseBodyAdviceBeans);}}6.使用RequestMappingHandlerMapping查找controller映射路徑
2019-01-16 09:47:07.758 INFO 8468 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/]}" onto public java.lang.String com.mkyong.WelcomeController.welcome(java.util.Map<java.lang.String, java.lang.Object>)定義:
/*** Creates {@link RequestMappingInfo} instances from type and method-level* {@link RequestMapping @RequestMapping} annotations in* {@link Controller @Controller} classes.** @author Arjen Poutsma* @author Rossen Stoyanchev* @author Sam Brannen* @since 3.1*/作用:使用注解@RequestMapping在controller類內創建一個類型或者方法級別的RequestMappingInfo實例
7.EndpointHandlerMapping映射的監控項
2019-01-15 14:19:30.985 INFO 9440 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/trace || /trace.json],methods=[GET],produces=[application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke() 2019-01-15 14:19:30.986 INFO 9440 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/health || /health.json],produces=[application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.HealthMvcEndpoint.invoke(java.security.Principal) 2019-01-15 14:19:30.987 INFO 9440 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/metrics/{name:.*}],methods=[GET],produces=[application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.MetricsMvcEndpoint.value(java.lang.String) 2019-01-15 14:19:30.987 INFO 9440 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/metrics || /metrics.json],methods=[GET],produces=[application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke() 2019-01-15 14:19:30.988 INFO 9440 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/dump || /dump.json],methods=[GET],produces=[application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke() 2019-01-15 14:19:30.988 INFO 9440 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/heapdump || /heapdump.json],methods=[GET],produces=[application/octet-stream]}" onto public void org.springframework.boot.actuate.endpoint.mvc.HeapdumpMvcEndpoint.invoke(boolean,javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse) throws java.io.IOException,javax.servlet.ServletException 2019-01-15 14:19:30.989 INFO 9440 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/beans || /beans.json],methods=[GET],produces=[application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke() 2019-01-15 14:19:30.990 INFO 9440 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/autoconfig || /autoconfig.json],methods=[GET],produces=[application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke() 2019-01-15 14:19:30.992 INFO 9440 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/env/{name:.*}],methods=[GET],produces=[application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EnvironmentMvcEndpoint.value(java.lang.String) 2019-01-15 14:19:30.992 INFO 9440 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/env || /env.json],methods=[GET],produces=[application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke() 2019-01-15 14:19:30.995 INFO 9440 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/info || /info.json],methods=[GET],produces=[application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke() 2019-01-15 14:19:30.996 INFO 9440 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/mappings || /mappings.json],methods=[GET],produces=[application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke() 2019-01-15 14:19:30.996 INFO 9440 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/configprops || /configprops.json],methods=[GET],produces=[application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()其中,
/trace 通過EndpointMvcAdapter.invoke()觸發TraceEndpoint的invoke方法
/health通過HealthMvcEndpoint.invoke()觸發
/metrics/{name:.*}通過MetricsMvcEndpoint.value()觸發
/metrics通過EndpointMvcAdapter.invoke()觸發MetricsEndpoint的invoke方法
/dump通過EndpointMvcAdapter.invoke()觸發DumpEndpoint的invoke方法
/heapdump通過HeapdumpMvcEndpoint.invoke()觸發
/beans通過EndpointMvcAdapter.invoke()觸發BeansEndpoint的invoke方法
/autoconfig通過EndpointMvcAdapter.invoke()觸發AutoconfigEndpoint的invoke方法
/env/{name:.*}通過EnvironmentMvcEndpoint.value()方法觸發
/info通過EndpointMvcAdapter.invoke()觸發InfoEndpoint的invoke方法
/mappings通過通過EndpointMvcAdapter.invoke()觸發RequestMappingEndpoint的invoke方法
小結:
restful請求實現分兩種,一種通過EndpointMvcAdapter.invoke()觸發
而EndpointMvcAdapter.invoke()通過注解@GetMapping實現了restful服務
/*** Adapter class to expose {@link Endpoint}s as {@link MvcEndpoint}s.** @author Dave Syer* @author Andy Wilkinson*/ public class EndpointMvcAdapter extends AbstractEndpointMvcAdapter<Endpoint<?>> {/*** Create a new {@link EndpointMvcAdapter}.* @param delegate the underlying {@link Endpoint} to adapt.*/public EndpointMvcAdapter(Endpoint<?> delegate) {super(delegate);}@Override@GetMapping(produces = MediaType.APPLICATION_JSON_VALUE)@ResponseBodypublic Object invoke() {return super.invoke();}}另一種,通過繼承MvcEndpoint的invoke方法來觸發?
例如HealthMvcEndpoint
@RequestMapping(produces = MediaType.APPLICATION_JSON_VALUE)@ResponseBodypublic Object invoke(Principal principal) {if (!getDelegate().isEnabled()) {// Shouldn't happen because the request mapping should not be registeredreturn getDisabledResponse();}Health health = getHealth(principal);HttpStatus status = getStatus(health);if (status != null) {return new ResponseEntity<Health>(health, status);}return health;}7.1 EndpointHandlerMapping的定義
/*** {@link HandlerMapping} to map {@link Endpoint}s to URLs via {@link Endpoint#getId()}.* The semantics of {@code @RequestMapping} should be identical to a normal* {@code @Controller}, but the endpoints should not be annotated as {@code @Controller}* (otherwise they will be mapped by the normal MVC mechanisms).* <p>* One of the aims of the mapping is to support endpoints that work as HTTP endpoints but* can still provide useful service interfaces when there is no HTTP server (and no Spring* MVC on the classpath). Note that any endpoints having method signatures will break in a* non-servlet environment.** @author Phillip Webb* @author Christian Dupuis* @author Dave Syer*/7.2 層次結構
7.3 查看對應的bean的生成
{"bean": "endpointHandlerMapping","aliases": [],"scope": "singleton","type": "org.springframework.boot.actuate.endpoint.mvc.EndpointHandlerMapping","resource": "class path resource [org/springframework/boot/actuate/autoconfigure/EndpointWebMvcManagementContextConfiguration.class]","dependencies": []}?7.4 獲取流程
@Bean@ConditionalOnMissingBeanpublic EndpointHandlerMapping endpointHandlerMapping() {Set<? extends MvcEndpoint> endpoints = mvcEndpoints().getEndpoints(); //1CorsConfiguration corsConfiguration = getCorsConfiguration(this.corsProperties); EndpointHandlerMapping mapping = new EndpointHandlerMapping(endpoints,corsConfiguration); //2 boolean disabled = this.managementServerProperties.getPort() != null && this.managementServerProperties.getPort() == -1; mapping.setDisabled(disabled);if (!disabled) {mapping.setPrefix(this.managementServerProperties.getContextPath()); //3}if (this.mappingCustomizers != null) {for (EndpointHandlerMappingCustomizer customizer : this.mappingCustomizers) {customizer.customize(mapping); //4}}return mapping;}7.4.1 MvcEndpoints獲取endpoint定義
@Overridepublic void afterPropertiesSet() throws Exception {Collection<MvcEndpoint> existing = BeanFactoryUtils.beansOfTypeIncludingAncestors(this.applicationContext, MvcEndpoint.class).values();this.endpoints.addAll(existing);this.customTypes = findEndpointClasses(existing);@SuppressWarnings("rawtypes")Collection<Endpoint> delegates = BeanFactoryUtils.beansOfTypeIncludingAncestors(this.applicationContext, Endpoint.class).values();for (Endpoint<?> endpoint : delegates) {if (isGenericEndpoint(endpoint.getClass()) && endpoint.isEnabled()) {EndpointMvcAdapter adapter = new EndpointMvcAdapter(endpoint);String path = determinePath(endpoint,this.applicationContext.getEnvironment());if (path != null) {adapter.setPath(path);}this.endpoints.add(adapter);}}}7.4.2 定義映射關系
其內部實現源碼:
private String getPath(Object handler) {if (handler instanceof String) {handler = getApplicationContext().getBean((String) handler);}if (handler instanceof MvcEndpoint) {return ((MvcEndpoint) handler).getPath();}return "";}7.4.3 增加contextpath
7.4.4 自定義EndpointHandlerMappingCustomizer
8.其它通過
@Bean@ConditionalOnBean(EnvironmentEndpoint.class)@ConditionalOnEnabledEndpoint("env")public EnvironmentMvcEndpoint environmentMvcEndpoint(EnvironmentEndpoint delegate) {return new EnvironmentMvcEndpoint(delegate);}@Bean@ConditionalOnMissingBean@ConditionalOnEnabledEndpoint("heapdump")public HeapdumpMvcEndpoint heapdumpMvcEndpoint() {return new HeapdumpMvcEndpoint();}@Bean@ConditionalOnBean(HealthEndpoint.class)@ConditionalOnEnabledEndpoint("health")public HealthMvcEndpoint healthMvcEndpoint(HealthEndpoint delegate,ManagementServerProperties managementServerProperties) {HealthMvcEndpoint healthMvcEndpoint = new HealthMvcEndpoint(delegate,isHealthSecure(), managementServerProperties.getSecurity().getRoles());if (this.healthMvcEndpointProperties.getMapping() != null) {healthMvcEndpoint.addStatusMapping(this.healthMvcEndpointProperties.getMapping());}return healthMvcEndpoint;}@Bean@ConditionalOnBean(MetricsEndpoint.class)@ConditionalOnEnabledEndpoint("metrics")public MetricsMvcEndpoint metricsMvcEndpoint(MetricsEndpoint delegate) {return new MetricsMvcEndpoint(delegate);}@Bean@ConditionalOnEnabledEndpoint("logfile")@Conditional(LogFileCondition.class)public LogFileMvcEndpoint logfileMvcEndpoint() {return new LogFileMvcEndpoint();}@Bean@ConditionalOnBean(ShutdownEndpoint.class)@ConditionalOnEnabledEndpoint(value = "shutdown", enabledByDefault = false)public ShutdownMvcEndpoint shutdownMvcEndpoint(ShutdownEndpoint delegate) {return new ShutdownMvcEndpoint(delegate);}?以health為例
@RequestMapping(produces = MediaType.APPLICATION_JSON_VALUE)@ResponseBodypublic Object invoke(Principal principal) {if (!getDelegate().isEnabled()) {// Shouldn't happen because the request mapping should not be registeredreturn getDisabledResponse();} Health health = getHealth(principal);HttpStatus status = getStatus(health);if (status != null) {return new ResponseEntity<Health>(health, status);}return health;}調用HealthEndpoint
/*** Invoke all {@link HealthIndicator} delegates and collect their health information.*/@Overridepublic Health invoke() {return this.healthIndicator.health();}?總結:
spring boot提供http請求的方式可以分兩種:
1.通過查找@Controller注解中的@RequestMapping來形成HandlerMapping
2.直接通過@RequestMapping來形成HandlerMapping如actuator模塊,這里面又分成兩種:
? ?2.1??一種集中式的通過繼承@RequestMapping來實現如通過EndpointMvcAdapter.invoke()觸發
? ?2.2? 另一種通過直接的@RequestMapping注解實現
3.spring boot1.x監控的實現
/trace 通過EndpointMvcAdapter.invoke()觸發TraceEndpoint的invoke方法
/health通過HealthMvcEndpoint.invoke()觸發
/metrics/{name:.*}通過MetricsMvcEndpoint.value()觸發
/metrics通過EndpointMvcAdapter.invoke()觸發MetricsEndpoint的invoke方法
/dump通過EndpointMvcAdapter.invoke()觸發DumpEndpoint的invoke方法
/heapdump通過HeapdumpMvcEndpoint.invoke()觸發
/beans通過EndpointMvcAdapter.invoke()觸發BeansEndpoint的invoke方法
/autoconfig通過EndpointMvcAdapter.invoke()觸發AutoconfigEndpoint的invoke方法
/env/{name:.*}通過EnvironmentMvcEndpoint.value()方法觸發
/info通過EndpointMvcAdapter.invoke()觸發InfoEndpoint的invoke方法
/mappings通過通過EndpointMvcAdapter.invoke()觸發RequestMappingEndpoint的invoke方法。
?4. 這些實現都定義在spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ org.springframework.boot.actuate.autoconfigure.AuditAutoConfiguration,\ org.springframework.boot.actuate.autoconfigure.CacheStatisticsAutoConfiguration,\ org.springframework.boot.actuate.autoconfigure.CrshAutoConfiguration,\ org.springframework.boot.actuate.autoconfigure.EndpointAutoConfiguration,\ org.springframework.boot.actuate.autoconfigure.EndpointMBeanExportAutoConfiguration,\ org.springframework.boot.actuate.autoconfigure.EndpointWebMvcAutoConfiguration,\ org.springframework.boot.actuate.autoconfigure.HealthIndicatorAutoConfiguration,\ org.springframework.boot.actuate.autoconfigure.InfoContributorAutoConfiguration,\ org.springframework.boot.actuate.autoconfigure.JolokiaAutoConfiguration,\ org.springframework.boot.actuate.autoconfigure.ManagementServerPropertiesAutoConfiguration,\ org.springframework.boot.actuate.autoconfigure.ManagementWebSecurityAutoConfiguration,\ org.springframework.boot.actuate.autoconfigure.MetricFilterAutoConfiguration,\ org.springframework.boot.actuate.autoconfigure.MetricRepositoryAutoConfiguration,\ org.springframework.boot.actuate.autoconfigure.MetricsDropwizardAutoConfiguration,\ org.springframework.boot.actuate.autoconfigure.MetricsChannelAutoConfiguration,\ org.springframework.boot.actuate.autoconfigure.MetricExportAutoConfiguration,\ org.springframework.boot.actuate.autoconfigure.PublicMetricsAutoConfiguration,\ org.springframework.boot.actuate.autoconfigure.TraceRepositoryAutoConfiguration,\ org.springframework.boot.actuate.autoconfigure.TraceWebFilterAutoConfigurationorg.springframework.boot.actuate.autoconfigure.ManagementContextConfiguration=\ org.springframework.boot.actuate.autoconfigure.EndpointWebMvcManagementContextConfiguration,\ org.springframework.boot.actuate.autoconfigure.EndpointWebMvcHypermediaManagementContextConfiguration?
轉載于:https://www.cnblogs.com/davidwang456/p/10272999.html
總結
以上是生活随笔為你收集整理的如何做自己的服务监控?spring boot 1.x服务监控揭秘的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Spring Boot 2.0官方文档之
- 下一篇: How web servers work