您现在的位置是:首页 > 正文

聊聊springboot的liveness及readiness

2023-10-24 10:50:23阅读 2561

本文主要研究一下springboot的liveness及readiness

使用

management:
  endpoints:
    web:
      exposure:
        include: '*'
  endpoint:
    health:
      probes:
        enabled: true
      show-details: always
  health:
    # /actuator/health/liveness
    livenessState:
      enabled: true
    # /actuator/health/readiness
    readinessState:
      enabled: true      

通过如上配置可以开启liveness及readiness,要求springboot版本在2.3.0及以上

ApplicationAvailabilityAutoConfiguration

org/springframework/boot/autoconfigure/availability/ApplicationAvailabilityAutoConfiguration.java

@Configuration(proxyBeanMethods = false)
public class ApplicationAvailabilityAutoConfiguration {

	@Bean
	public ApplicationAvailabilityBean applicationAvailability() {
		return new ApplicationAvailabilityBean();
	}

}

ApplicationAvailabilityAutoConfiguration定义了ApplicationAvailabilityBean

ApplicationAvailabilityBean

org/springframework/boot/availability/ApplicationAvailabilityBean.java

public class ApplicationAvailabilityBean
		implements ApplicationAvailability, ApplicationListener<AvailabilityChangeEvent<?>> {

	private final Map<Class<? extends AvailabilityState>, AvailabilityChangeEvent<?>> events = new HashMap<>();

	@Override
	public <S extends AvailabilityState> S getState(Class<S> stateType, S defaultState) {
		Assert.notNull(stateType, "StateType must not be null");
		Assert.notNull(defaultState, "DefaultState must not be null");
		S state = getState(stateType);
		return (state != null) ? state : defaultState;
	}

	@Override
	public <S extends AvailabilityState> S getState(Class<S> stateType) {
		AvailabilityChangeEvent<S> event = getLastChangeEvent(stateType);
		return (event != null) ? event.getState() : null;
	}

	@Override
	@SuppressWarnings("unchecked")
	public <S extends AvailabilityState> AvailabilityChangeEvent<S> getLastChangeEvent(Class<S> stateType) {
		return (AvailabilityChangeEvent<S>) this.events.get(stateType);
	}

	@Override
	public void onApplicationEvent(AvailabilityChangeEvent<?> event) {
		Class<? extends AvailabilityState> stateType = getStateType(event.getState());
		this.events.put(stateType, event);
	}

	@SuppressWarnings("unchecked")
	private Class<? extends AvailabilityState> getStateType(AvailabilityState state) {
		if (state instanceof Enum) {
			return (Class<? extends AvailabilityState>) ((Enum<?>) state).getDeclaringClass();
		}
		return state.getClass();
	}

}

ApplicationAvailabilityBean实现了ApplicationAvailability、ApplicationListener接口,它接收AvailabilityChangeEvent事件,然后存储到events中,getState方法则从events中获取指定class类型的AvailabilityState

AvailabilityChangeEvent

org/springframework/boot/availability/AvailabilityChangeEvent.java

public class AvailabilityChangeEvent<S extends AvailabilityState> extends PayloadApplicationEvent<S> {

	/**
	 * Create a new {@link AvailabilityChangeEvent} instance.
	 * @param source the source of the event
	 * @param state the availability state (never {@code null})
	 */
	public AvailabilityChangeEvent(Object source, S state) {
		super(source, state);
	}

	/**
	 * Return the changed availability state.
	 * @return the availability state
	 */
	public S getState() {
		return getPayload();
	}

	@Override
	public ResolvableType getResolvableType() {
		return ResolvableType.forClassWithGenerics(getClass(), getStateType());
	}

	private Class<?> getStateType() {
		S state = getState();
		if (state instanceof Enum) {
			return ((Enum<?>) state).getDeclaringClass();
		}
		return state.getClass();
	}

	/**
	 * Convenience method that can be used to publish an {@link AvailabilityChangeEvent}
	 * to the given application context.
	 * @param <S> the availability state type
	 * @param context the context used to publish the event
	 * @param state the changed availability state
	 */
	public static <S extends AvailabilityState> void publish(ApplicationContext context, S state) {
		Assert.notNull(context, "Context must not be null");
		publish(context, context, state);
	}

	/**
	 * Convenience method that can be used to publish an {@link AvailabilityChangeEvent}
	 * to the given application context.
	 * @param <S> the availability state type
	 * @param publisher the publisher used to publish the event
	 * @param source the source of the event
	 * @param state the changed availability state
	 */
	public static <S extends AvailabilityState> void publish(ApplicationEventPublisher publisher, Object source,
			S state) {
		Assert.notNull(publisher, "Publisher must not be null");
		publisher.publishEvent(new AvailabilityChangeEvent<>(source, state));
	}

}

AvailabilityChangeEvent继承了PayloadApplicationEvent,它还定义了publish方法

AvailabilityHealthContributorAutoConfiguration

org/springframework/boot/actuate/autoconfigure/availability/AvailabilityHealthContributorAutoConfiguration.java

@Configuration(proxyBeanMethods = false)
@AutoConfigureAfter(ApplicationAvailabilityAutoConfiguration.class)
public class AvailabilityHealthContributorAutoConfiguration {

	@Bean
	@ConditionalOnMissingBean(name = "livenessStateHealthIndicator")
	@ConditionalOnProperty(prefix = "management.health.livenessstate", name = "enabled", havingValue = "true")
	public LivenessStateHealthIndicator livenessStateHealthIndicator(ApplicationAvailability applicationAvailability) {
		return new LivenessStateHealthIndicator(applicationAvailability);
	}

	@Bean
	@ConditionalOnMissingBean(name = "readinessStateHealthIndicator")
	@ConditionalOnProperty(prefix = "management.health.readinessstate", name = "enabled", havingValue = "true")
	public ReadinessStateHealthIndicator readinessStateHealthIndicator(
			ApplicationAvailability applicationAvailability) {
		return new ReadinessStateHealthIndicator(applicationAvailability);
	}

}

AvailabilityHealthContributorAutoConfiguration定义了LivenessStateHealthIndicator、ReadinessStateHealthIndicator

AvailabilityStateHealthIndicator

org/springframework/boot/actuate/availability/AvailabilityStateHealthIndicator.java

public class AvailabilityStateHealthIndicator extends AbstractHealthIndicator {

	private final ApplicationAvailability applicationAvailability;

	private Class<? extends AvailabilityState> stateType;

	private final Map<AvailabilityState, Status> statusMappings = new HashMap<>();

	/**
	 * Create a new {@link AvailabilityStateHealthIndicator} instance.
	 * @param <S> the availability state type
	 * @param applicationAvailability the application availability
	 * @param stateType the availability state type
	 * @param statusMappings consumer used to setup the status mappings
	 */
	public <S extends AvailabilityState> AvailabilityStateHealthIndicator(
			ApplicationAvailability applicationAvailability, Class<S> stateType,
			Consumer<StatusMappings<S>> statusMappings) {
		Assert.notNull(applicationAvailability, "ApplicationAvailability must not be null");
		Assert.notNull(stateType, "StateType must not be null");
		Assert.notNull(statusMappings, "StatusMappings must not be null");
		this.applicationAvailability = applicationAvailability;
		this.stateType = stateType;
		statusMappings.accept(this.statusMappings::put);
		assertAllEnumsMapped(stateType);
	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	private <S extends AvailabilityState> void assertAllEnumsMapped(Class<S> stateType) {
		if (!this.statusMappings.containsKey(null) && Enum.class.isAssignableFrom(stateType)) {
			EnumSet elements = EnumSet.allOf((Class) stateType);
			for (Object element : elements) {
				Assert.isTrue(this.statusMappings.containsKey(element),
						() -> "StatusMappings does not include " + element);
			}
		}
	}

	@Override
	protected void doHealthCheck(Builder builder) throws Exception {
		AvailabilityState state = getState(this.applicationAvailability);
		Status status = this.statusMappings.get(state);
		if (status == null) {
			status = this.statusMappings.get(null);
		}
		Assert.state(status != null, () -> "No mapping provided for " + state);
		builder.status(status);
	}

	/**
	 * Return the current availability state. Subclasses can override this method if a
	 * different retrieval mechanism is needed.
	 * @param applicationAvailability the application availability
	 * @return the current availability state
	 */
	protected AvailabilityState getState(ApplicationAvailability applicationAvailability) {
		return applicationAvailability.getState(this.stateType);
	}

	/**
	 * Callback used to add status mappings.
	 *
	 * @param <S> the availability state type
	 */
	public interface StatusMappings<S extends AvailabilityState> {

		/**
		 * Add the status that should be used if no explicit mapping is defined.
		 * @param status the default status
		 */
		default void addDefaultStatus(Status status) {
			add(null, status);
		}

		/**
		 * Add a new status mapping .
		 * @param availabilityState the availability state
		 * @param status the mapped status
		 */
		void add(S availabilityState, Status status);

	}

}

AvailabilityStateHealthIndicator继承了AbstractHealthIndicator,它定义了statusMappings,key为AvailabilityState,value为Status,其doHealthCheck就是获取state,然后从statusMappings取出对应的status

LivenessStateHealthIndicator

org/springframework/boot/actuate/availability/LivenessStateHealthIndicator.java

public class LivenessStateHealthIndicator extends AvailabilityStateHealthIndicator {

	public LivenessStateHealthIndicator(ApplicationAvailability availability) {
		super(availability, LivenessState.class, (statusMappings) -> {
			statusMappings.add(LivenessState.CORRECT, Status.UP);
			statusMappings.add(LivenessState.BROKEN, Status.DOWN);
		});
	}

	@Override
	protected AvailabilityState getState(ApplicationAvailability applicationAvailability) {
		return applicationAvailability.getLivenessState();
	}

}

LivenessStateHealthIndicator继承了AvailabilityStateHealthIndicator,它建立了LivenessState.CORRECT到Status.UP,LivenessState.BROKEN到Status.DOWN的映射

ReadinessStateHealthIndicator

org/springframework/boot/actuate/availability/ReadinessStateHealthIndicator.java

public class ReadinessStateHealthIndicator extends AvailabilityStateHealthIndicator {

	public ReadinessStateHealthIndicator(ApplicationAvailability availability) {
		super(availability, ReadinessState.class, (statusMappings) -> {
			statusMappings.add(ReadinessState.ACCEPTING_TRAFFIC, Status.UP);
			statusMappings.add(ReadinessState.REFUSING_TRAFFIC, Status.OUT_OF_SERVICE);
		});
	}

	@Override
	protected AvailabilityState getState(ApplicationAvailability applicationAvailability) {
		return applicationAvailability.getReadinessState();
	}

}

ReadinessStateHealthIndicator继承了AvailabilityStateHealthIndicator,它定义了ReadinessState.ACCEPTING_TRAFFIC到Status.UP,ReadinessState.REFUSING_TRAFFIC到Status.OUT_OF_SERVICE的映射

EventPublishingRunListener

org/springframework/boot/context/event/EventPublishingRunListener.java

public class EventPublishingRunListener implements SpringApplicationRunListener, Ordered {
	@Override
	public void started(ConfigurableApplicationContext context) {
		context.publishEvent(new ApplicationStartedEvent(this.application, this.args, context));
		AvailabilityChangeEvent.publish(context, LivenessState.CORRECT);
	}

	@Override
	public void running(ConfigurableApplicationContext context) {
		context.publishEvent(new ApplicationReadyEvent(this.application, this.args, context));
		AvailabilityChangeEvent.publish(context, ReadinessState.ACCEPTING_TRAFFIC);
	}
}

EventPublishingRunListener的started方法会发布AvailabilityChangeEvent,其state为LivenessState.CORRECT;running方法会发布AvailabilityChangeEvent,其state为ReadinessState.ACCEPTING_TRAFFIC

SpringApplicationRunListeners

org/springframework/boot/SpringApplicationRunListeners.java

class SpringApplicationRunListeners {

	void started(ConfigurableApplicationContext context) {
		for (SpringApplicationRunListener listener : this.listeners) {
			listener.started(context);
		}
	}

	void running(ConfigurableApplicationContext context) {
		for (SpringApplicationRunListener listener : this.listeners) {
			listener.running(context);
		}
	}

	//......
}	

SpringApplicationRunListeners的started会回调listener的started,running会回调listener的running方法

ServletWebServerApplicationContext

org/springframework/boot/web/servlet/context/ServletWebServerApplicationContext.java

public class ServletWebServerApplicationContext extends GenericWebApplicationContext
		implements ConfigurableWebServerApplicationContext {

	@Override
	protected void doClose() {
		if (isActive()) {
			AvailabilityChangeEvent.publish(this, ReadinessState.REFUSING_TRAFFIC);
		}
		super.doClose();
	}

	//......
}	

ServletWebServerApplicationContext的doClose方法在active的时候会发布AvailabilityChangeEvent,state为ReadinessState.REFUSING_TRAFFIC

SpringApplication

org/springframework/boot/SpringApplication.java

public ConfigurableApplicationContext run(String... args) {
		StopWatch stopWatch = new StopWatch();
		stopWatch.start();
		ConfigurableApplicationContext context = null;
		Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
		configureHeadlessProperty();
		SpringApplicationRunListeners listeners = getRunListeners(args);
		listeners.starting();
		try {
			ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
			ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
			configureIgnoreBeanInfo(environment);
			Banner printedBanner = printBanner(environment);
			context = createApplicationContext();
			exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
					new Class[] { ConfigurableApplicationContext.class }, context);
			prepareContext(context, environment, listeners, applicationArguments, printedBanner);
			refreshContext(context);
			afterRefresh(context, applicationArguments);
			stopWatch.stop();
			if (this.logStartupInfo) {
				new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
			}
			listeners.started(context);
			callRunners(context, applicationArguments);
		}
		catch (Throwable ex) {
			handleRunFailure(context, ex, exceptionReporters, listeners);
			throw new IllegalStateException(ex);
		}

		try {
			listeners.running(context);
		}
		catch (Throwable ex) {
			handleRunFailure(context, ex, exceptionReporters, null);
			throw new IllegalStateException(ex);
		}
		return context;
	}

SpringApplication的run方法会先获取SpringApplicationRunListeners,然后执行listeners.starting(),接着prepareEnvironment、createApplicationContext、prepareContext、refreshContext、afterRefresh;之后执行listeners.started(context);再执行listeners.running(context)

小结

AvailabilityHealthContributorAutoConfiguration定义了LivenessStateHealthIndicator、ReadinessStateHealthIndicator,它们依赖AvailabilityChangeEvent,SpringApplication的run方法会先后触发listeners.starting()、listeners.started(context)、listeners.running(context);EventPublishingRunListener的started方法会发布AvailabilityChangeEvent,其state为LivenessState.CORRECT;running方法会发布AvailabilityChangeEvent,其state为ReadinessState.ACCEPTING_TRAFFIC。

网站文章

  • 容器,Pod,Kubernetes,节点这四个基本概念以及互相之间运用关系,概念、原理解读,以及Pod中特殊pause容器

    容器,Pod,Kubernetes,节点这四个基本概念以及互相之间运用关系,概念、原理解读,以及Pod中特殊pause容器

    容器,Pod,Kubernetes,节点这四个基本概念以及互相之间运用关系,概念、原理解读,以及Pod中特殊pause容器

    2023-10-24 10:49:51
  • 【软考】系统集成项目管理工程师(八)项目进度管理【4分】

    【软考】系统集成项目管理工程师(八)项目进度管理【4分】

    识别和记录为完成项目可交付成果而需采取的所有活动识别和记录项目活动之间的关系的过程;定义工作之间的逻辑顺序,以便在既定的所有项目制约因素下获得最高的效率估算执行各项活动所需的材料、人员、设备或用品的种类和数量的过程;明确完成活动所需的资源种类、数量和特性,以便做出更准确的成本和持续时间估算;估算活动资源过程与估算成本过程紧密相关;根据资源估算的结果,估算完成单项活动所需工作时段数的过程,确定完成每

    2023-10-24 10:49:47
  • java spring cloud 企业工程管理系统源码+二次开发+定制化服务

    java spring cloud 企业工程管理系统源码+二次开发+定制化服务

    项目计划管理:计划的查询、新增、编辑、删除、甘特图保存为基线、设置为模板、任务时间及顺序调整、全局资源配置、引用系统模板、导入project文件、导出XML文件等功能。工程竣工验收:工程竣工验收的查询、新增、编辑、查看、删除、附件上传、验收异常填写异常信息、选择整改部门和责任人等功能。质量检查:质量检查的查询、新增、编辑、查看、删除、附件上传、验收异常填写异常信息、选择整改部门和责任人等功能。项目

    2023-10-24 10:49:43
  • asp.net网上商城系统VS开发sqlserver数据库web结构c#编程Microsoft Visual Studio协同过滤设计

    asp.net网上商城系统VS开发sqlserver数据库web结构c#编程Microsoft Visual Studio协同过滤设计

    asp.net网上商城系统是一套完善的web设计管理系统系统采用协同过滤算法进行商品推荐,系统具有完整的源代码和数据库,系统主要采用B/S模式开发。2、开发环境为vs2010,数据库为sqlserver2008,或者 以上版本都可以,使用c#语言开发。7、在浏览商品的信息 根据用户浏览记录,结合协同过滤算法进行计算,给出 可能访问其他的商品信息推荐。3、对商品的基本信息进行添加、修改、删除和查看;

    2023-10-24 10:49:11
  • 五个步骤轻松搞定软件开发流程

    五个步骤轻松搞定软件开发流程

    互联网在当今社会非常普遍,日常生活中很多东西都离不开互联网,应用软件是互联网必不可少的载体和终端。因此,软件是互联网中不可缺少的关键因素。软件开发已经成为许多企业和企业家非常重要的布局。在软件开发之前,我们应该了解软件开发过程,最好在设计前梳理一张软件开发过程图。本文将为您详细介绍软件开发流程。

    2023-10-24 10:49:05
  • 这些lodash方法真香!!

    Lodash 是一个一致性、模块化、高性能的 JavaScript 实用工具库。Lodash官网Lodash 通过降低 array、number、objects、string 等等的使用难度从而让 JavaScript 变得更简单。Lodash 的模块化方法 非常适用于:1、 遍历 array、object 和 string2、对值进行操作和检测3、创建符合功能的函数lodash-es模块使得我们

    2023-10-24 10:48:09
  • activiti7.0工作流,举个例子实现自定义任务监听和执行监听代码

    activiti7.0,自定义任务监听、执行监听

    2023-10-24 10:47:33
  • golang redis lua脚本 和 lua function

    golang redis lua脚本 和 lua function

    golang redis lua脚本 和 lua function

    2023-10-24 10:47:26
  • Android APP 隐藏系统软键盘的方法

    Android APP 隐藏系统软键盘的方法

    Text。

    2023-10-24 10:42:49
  • 【安卓APP开发】遇到的小问题

    【安卓APP开发】遇到的小问题

    一、gradle不匹配二、 AS版本过低

    2023-10-24 10:42:20