分析SpringBoot Actuator优雅停机自定义容器重启Actuator

最近在研究SpringBoot Actuator,发现其提供了一个很特殊的功能,可以进行优雅停机,用户只需要引入SpringBoot Actuator,然后在application.properties中将endpoints.shutdown.enabled=true开启即可。然后我们只需要使用http post提交方式调用host:port/shutdown就可以实现优雅停机。那么SpringBoot是怎么做到的呢,于是便好奇地开启了源码阅读。

SpringBoot中每个请求/info,/health都是通过Endpoint的invoke方法来处理的,他将请求委托给了MvcEndpoint来进行处理。简单情况下,我们要自定义Endpoint只需要实现Endpoint并将其注入到spring上下文即可。SpringBoot是通过EndpointAutoConfiguration来注入组件的。但是如果我们要以Mvc的方式来注入就需要实现MvcEndpoint了,然后通过EndpointWebMvcManagementContextConfiguration来进行注入。最终通过重写了SpringMVC的RequestHandlerMapping的类EndpointHandlerMapping来对MvcEndpoint进行注册。所有的Actuator MvcEndpoint都是通过EndpointHandlerMapping的registerHandlerMethod来进行注册的。注册后就保存在EndpointHandlerMapping类的Set集合中。这样就以Mvc的方式暴露出来。

以SpringBoot的优雅停机Shutdown endpoint为例:

分析SpringBoot Actuator优雅停机自定义容器重启Actuator_第1张图片
分析SpringBoot Actuator优雅停机自定义容器重启Actuator_第2张图片

至此表面ShutdownEndpoint是一个普通的Endpoint组件,我们将其注入spring上下文后就可以通过get方式调用了。但是根据官方文档他只能通过Post方式调用。原来其定义了一个ShutdownMvcEndpoint并限制了Post方式,参见下图:


分析SpringBoot Actuator优雅停机自定义容器重启Actuator_第3张图片

然后通过EndpointWebMvcManagementContextConfiguration来进行注入:


那么我们现在来实现一个容器重启的ReloadEndpoint就很简单了。

首先自定义ReloadEndpoint

分析SpringBoot Actuator优雅停机自定义容器重启Actuator_第4张图片
分析SpringBoot Actuator优雅停机自定义容器重启Actuator_第5张图片

注意其核心逻辑先将SpringContext上下文stop然后再start

再在application.properties中将reload enabled:  endpoints.reload.enabled=true

现在我们将其引入上下文就可以get调用了

@Bean

publicReloadEndpointreloadEndpoint(){

return newReloadEndpoint();

}

但是如果要使用post方式就需要增加MvcEndpoint了。

public class ReloadMvcEndpoint extends EndpointMvcAdapter {

publicReloadMvcEndpoint(ReloadEndpoint delegate) {

super(delegate);

}

@PostMapping(produces= { ActuatorMediaTypes.APPLICATION_ACTUATOR_V1_JSON_VALUE,

MediaType.APPLICATION_JSON_VALUE})

@ResponseBody

@Override

publicObjectinvoke() {

if(!getDelegate().isEnabled()) {

return newResponseEntity>(

Collections.singletonMap("message","This endpoint is disabled"),

HttpStatus.NOT_FOUND);

}

return super.invoke();

}

}

然后将其以Mvc方式暴露出去

@Bean

@ConditionalOnBean(ReloadEndpoint.class)

@ConditionalOnEnabledEndpoint(value="reload",enabledByDefault=false)

public ReloadMvcEndpoint reloadMvcEndpoint(ReloadEndpoint delegate) {

return newReloadMvcEndpoint(delegate);

}

通过页面Get方式调用会报错:


分析SpringBoot Actuator优雅停机自定义容器重启Actuator_第6张图片

通过post方式调用即可成功,见日志:


至此一个自定义endpoint就完成了,假如我们监控到某台机器很耗内存,我们就可以通过host:port/reload来进行重启应用了。

如果觉得我的文章对您有用,请关注我的微信公众号。长按图片识别二维码点击关注即可。


分析SpringBoot Actuator优雅停机自定义容器重启Actuator_第7张图片
@程序员

你可能感兴趣的:(分析SpringBoot Actuator优雅停机自定义容器重启Actuator)