作者:404,公众号404P,转载请注明出处。

前言

SOFABoot是蚂蚁金服的开源框架,在原有Spring Boot的基础上增强了不少能力,例如Readiness Check,类隔离,日志空间隔离等能力。除此之外,SOFABoot还可以方便的整合SOFA技术栈所包含的各类中间件。如果想要对SOFABoot有体感,可以参考这里快速构建一个SOFABoot的应用

本文来聊聊SOFABoot新增的Readiness健康检查机制。主要内容有以下几点:

  • liveness 和 readiness 的含义和区别
  • SOFABoot项目如何使用readiness的能力
  • SOFABoot是如何实现readiness的

一 Liveness 和Readiness

服务的健康检查,是微服务的基础能力,在微服务的运行时期定时地检查服务健康状态,为熔断降级等提供决策依据。那么说到健康检查,这里提出两个概念:liveness和readiness。这两个概念什么意思呢?有何区别呢?我们先看看在容器编排领域,k8s官网是在什么场景下提到这两个词的。

The kubelet uses liveness probes to know when to restart a Container. For example, liveness probes could catch a deadlock, where an application is running, but unable to make progress. Restarting a Container in such a state can help to make the application more available despite bugs.

The kubelet uses readiness probes to know when a Container is ready to start accepting traffic. A Pod is considered ready when all of its Containers are ready. One use of this signal is to control which Pods are used as backends for Services. When a Pod is not ready, it is removed from Service load balancers.

kubelet用liveness探针来检测应用在运行的过程中何时该重启一个容器。例如,liveness探针检测到一个应用在运行中陷入死锁状态,毫无进展,那么这个时候会重启容器暂时避免这种无解的运行状态,保持应用的正常运行。

kuelet用readiness探针来检测何时一个容器可以接受业务流量。当一个Pod中的所有容器都准备就绪了,这个Pod才被认为是准备就绪的,这个时候才会将容器放入到Service的负载均衡池中,对外提供服务。

所以,liveness的职责是在服务运行期,已经在跑业务时,定时检查服务是否正常;而readiness的职责则是在应用服务运行之前,判断该服务是否准备就绪,如果服务就绪了,负载均衡就可以将业务流量引入到该服务了。服务就绪往往有很多需要判断的,例如:各项配置是否加载完毕。如果这些提供服务前的准备工作未就绪,这个时候把流量放进来,就会有大量报错。

二 SOFABoot项目中使用Readiness Check

Readiness Check 在 SOFABoot中是个可选能力,通过starter的方式提供,如果需要使用,引入下方依赖即可:

<dependency>   <groupId>com.alipay.sofa</groupId>   <artifactId>healthcheck-sofa-boot-starter</artifactId> </dependency>

该starter包含了SpringBoot的健康检查spring-boot-starter-actuator。

在应用启动时,即可启动Readiness检查。

三 SOFABoot如何实现Readiness Check

我们到healthcheck-sofa-boot-starter对应的spring.factories文件看看有哪些自定义bean,其配置如下:

org.springframework.context.ApplicationContextInitializer=\ com.alipay.sofa.healthcheck.initializer.SofaBootHealthCheckInitializer  org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.alipay.sofa.healthcheck.configuration.SofaBootHealthCheckAutoConfiguration

配置了两个SOFABoot的实现类,一个是用应用初始化组件,一个是SOFABoot健康检查需要的配置类。

1 应用初始化

SofaBootHealthCheckInitializer

这个是SOFABoot对于ApplicationContextInitializer的实现,这个接口的主要职责是:在springcontext 刷新(refresh)之前,调用该接口的initialize做前置的初始化操作,我们看看SOFABoot初始化做了什么事情:

public class SofaBootHealthCheckInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {     @Override     public void initialize(ConfigurableApplicationContext applicationContext) {         Environment environment = applicationContext.getEnvironment();         if (SOFABootEnvUtils.isSpringCloudBootstrapEnvironment(environment)) {             return;         }         LOGGER.info("SOFABoot HealthCheck Starting!");     } }

初始化的时候,判断了当前是否为SpringCloud的引导上下文,如果是的话,则返回,不打印日志,如果不是的话,则打印日志。

这是什么逻辑? 首先,初始化逻辑里只做了一件事情:打印日志,并且是在非SpringCloud环境下才打印日志?其实这是一个兼容逻辑。在SpringCloud环境下,自定义的initializer会被调用两次initialize方法(参考 # issue1151 & # issue 232),SpringCloud会加载一个引导上下文(bootstrap context)进来,我们自己的应用程序会加载应用上下文(application context)进来,这两个同时存在,intialzie会调用两次。

isSpringCloudBootstrapEnvironment方法