SOFABoot的Readiness健康检查机制是怎样的

发布时间:2021-09-13 09:26:54 作者:柒染
来源:亿速云 阅读:123

今天就跟大家聊聊有关SOFABoot的Readiness健康检查机制是怎样的,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。


前言

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

本文来聊聊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.<br />

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方法就是为了区分是否为SpringCloud加载进来的引导上下文,从而屏蔽掉这次initialize执行,确保日志只会在应用上下文时输出,该方法主要是通过是否存在SpringCloud中的特定类来识别是否引入SpringCloud,这里就不赘述了,读者可自行查看。

2 SOFABoot实现Readiness的核心逻辑

2.1 核心Bean介绍

SofaBootHealthCheckAutoConfiguration

要搞清楚实现Readiness的核心实现,我们先看下SOFABoot到底装配了哪些bean,下面列了一些核心的bean。

@Configuration
public class SofaBootHealthCheckAutoConfiguration {
	
    @Bean
    public ReadinessCheckListener readinessCheckListener() {
        return new ReadinessCheckListener();
    }
    
    @Bean
    public HealthCheckerProcessor healthCheckerProcessor() {
        return new HealthCheckerProcessor();
    }

    @Bean
    public HealthIndicatorProcessor healthIndicatorProcessor() {
        return new HealthIndicatorProcessor();
    }

    @Bean
    public AfterReadinessCheckCallbackProcessor afterReadinessCheckCallbackProcessor() {
        return new AfterReadinessCheckCallbackProcessor();
    }
}

上面一共罗列了4个bean,一个是应用监听器ReadinessCheckListener,这个是入口逻辑,下文核心逻辑讲解将从这个类开始。

一个是Readiness检查完毕的后置处理器AfterReadinessCheckCallbackProcessor,这个职责也比较容易理解,当Readiness完成之后,就会执行去处理逻辑。

另外两个处理器则是健康检查的处理器,HealthCheckerProcessor是针对SOFABoot提供的HealthChecker类型的bean进行处理,HealthIndicatorProcesso是针对SpringBoot提供的HealthIndicator类型的bean进行处理。

2.2 核心逻辑解析

ReadinessCheckListener

这个监听器实现了ApplicationListener,并监听ContextRefreshedEvent事件,当应用上下文刷新完成后,触发监听器收到该事件,执行下面的逻辑。

// ReadinessCheckListener 接收到刷新事件后的执行逻辑
public void onApplicationEvent(ContextRefreshedEvent event) {
    if (applicationContext.equals(event.getApplicationContext())) {
        healthCheckerProcessor.init();
        healthIndicatorProcessor.init();
        afterReadinessCheckCallbackProcessor.init();
        readinessHealthCheck();
        readinessCheckFinish = true;
    }
}

接收到上下文的刷新事件后,主要做了四件事情,前面三件是为最后一件事情做准备的:

public void readinessHealthCheck() {
    if (skipAllCheck()) {
        logger.warn("Skip all readiness health check.");
    } else {
        if (skipComponent()) {
            logger.warn("Skip HealthChecker health check.");
        } else {
            healthCheckerStatus = healthCheckerProcessor
                .readinessHealthCheck(healthCheckerDetails);
        }
        if (skipIndicator()) {
            logger.warn("Skip HealthIndicator health check.");
        } else {
            healthIndicatorStatus = healthIndicatorProcessor
                .readinessHealthCheck(healthIndicatorDetails);
        }
    }
    healthCallbackStatus = afterReadinessCheckCallbackProcessor
        .afterReadinessCheckCallback(healthCallbackDetails);
    if (healthCheckerStatus && healthIndicatorStatus && healthCallbackStatus) {
        logger.info("Readiness check result: success");
    } else {
        logger.error("Readiness check result: fail");
    }
}

从上面的逻辑,我们可以看到HealthChecker和HealthIndicator的处理都是可以基于配置跳过的,不是必须执行的。当HealthChecker、HealthIndicator、ReadinessCheckCallback对应的处理器都执行成功之后,打印相应的结果信息。

核心逻辑,其实就是三个不同类型Bean的处理器,去遍历执行各自的bean集合,收集执行结果。

可以看出,SOFABoot提供的HealthChecker和SpringBoot提供的HealthIndicator职责有点类似,但是存在差异性,HealthChecker中是适合于Readiness的,其实现类指明重试次数retryCount和重试间隔retryTimeInterval,在应用刚启动时候,做Readiness检查不一定能一次性成功,那么就需要这种最大重试机制,所以HealthChecker的处理器在readinessHealthCheck过程中持续的时间会更长。

public interface HealthChecker {
	// some method..
    default int getRetryCount() {
        return 0;
    }
    default long getRetryTimeInterval(){
        return 0;
    }
	// some method..
}

而SpringBoot本身提供的是Liveness机制,所以HealthIndicator在运行期间,本身就是一直定时去获取的,没有最大重试次数,只要一直在运行,就要定时去检查。

public interface HealthIndicator {
	// Return an indication of health.
	Health health();
}

当然,SOFABoot在重试完成了HealthCheck的健康检查之后,再完成了一遍HealthIndicator的健康检查,且执行了一遍后置逻辑,都成功之后,检查结果才是健康的,才可以正式对外提供服务。

显然,要扩展自己的检查指标也是很容易的,如果是要Readiness Check的,则实现一个HealthCheck类,如果是需要Liveness Check的,则实现一个HealthIndicator即可。

四 结语

本文开篇介绍了SOFABoot和SpringBoot的关系,在SpringBoot的健康检查中,提供了Liveness Check能力,SOFABoot在此之上新增了Readiness Check能力。通过starter的配置一步一步找到其入口逻辑,并对应用监听器、HealthCheck、HealthIndicator和ReadinessCheckCallback对应的三个处理的逻辑进行了核心解读,并说明了HealthCheck和HealthIndicator的区别。

看完上述内容,你们对SOFABoot的Readiness健康检查机制是怎样的有进一步的了解吗?如果还想了解更多知识或者相关内容,请关注亿速云行业资讯频道,感谢大家的支持。

推荐阅读:
  1. kubernetes系列教程(八)Pod健康检查机制
  2. kubernetes Readiness and liveness and startupProbe

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

readiness

上一篇:怎么用代码将github仓库里某个issue同步到CSDN博客上

下一篇:高并发测试工具Tsung使用方法

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》