Polish Liveness and Readiness support

This commit moves the core Liveness and Readiness support to its own
`availability` package. We've made this a core concept independent of
Kubernetes.

Spring Boot now produces `LivenessStateChanged` and
`ReadinessStateChanged` events as part of the typical application
lifecycle.

Liveness and Readiness Probes (`HealthIndicator` components and health
groups) are still configured only when deployed on Kubernetes.

This commit also improves the documentation around Probes best practices
and container lifecycle considerations.

See gh-19593
This commit is contained in:
Brian Clozel
2020-03-20 23:49:28 +01:00
parent 3edc1c3a7d
commit ffdf9a422f
30 changed files with 521 additions and 354 deletions

View File

@@ -14,13 +14,13 @@
* limitations under the License.
*/
package org.springframework.boot.actuate.kubernetes;
package org.springframework.boot.actuate.availability;
import org.springframework.boot.actuate.health.AbstractHealthIndicator;
import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.HealthIndicator;
import org.springframework.boot.kubernetes.ApplicationStateProvider;
import org.springframework.boot.kubernetes.LivenessState;
import org.springframework.boot.availability.ApplicationAvailabilityProvider;
import org.springframework.boot.availability.LivenessState;
/**
* A {@link HealthIndicator} that checks the {@link LivenessState} of the application.
@@ -30,15 +30,15 @@ import org.springframework.boot.kubernetes.LivenessState;
*/
public class LivenessProbeHealthIndicator extends AbstractHealthIndicator {
private final ApplicationStateProvider applicationStateProvider;
private final ApplicationAvailabilityProvider applicationAvailabilityProvider;
public LivenessProbeHealthIndicator(ApplicationStateProvider applicationStateProvider) {
this.applicationStateProvider = applicationStateProvider;
public LivenessProbeHealthIndicator(ApplicationAvailabilityProvider applicationAvailabilityProvider) {
this.applicationAvailabilityProvider = applicationAvailabilityProvider;
}
@Override
protected void doHealthCheck(Health.Builder builder) throws Exception {
if (LivenessState.live().equals(this.applicationStateProvider.getLivenessState())) {
if (LivenessState.live().equals(this.applicationAvailabilityProvider.getLivenessState())) {
builder.up();
}
else {

View File

@@ -14,13 +14,13 @@
* limitations under the License.
*/
package org.springframework.boot.actuate.kubernetes;
package org.springframework.boot.actuate.availability;
import org.springframework.boot.actuate.health.AbstractHealthIndicator;
import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.HealthIndicator;
import org.springframework.boot.kubernetes.ApplicationStateProvider;
import org.springframework.boot.kubernetes.ReadinessState;
import org.springframework.boot.availability.ApplicationAvailabilityProvider;
import org.springframework.boot.availability.ReadinessState;
/**
* A {@link HealthIndicator} that checks the {@link ReadinessState} of the application.
@@ -30,15 +30,15 @@ import org.springframework.boot.kubernetes.ReadinessState;
*/
public class ReadinessProbeHealthIndicator extends AbstractHealthIndicator {
private final ApplicationStateProvider applicationStateProvider;
private final ApplicationAvailabilityProvider applicationAvailabilityProvider;
public ReadinessProbeHealthIndicator(ApplicationStateProvider applicationStateProvider) {
this.applicationStateProvider = applicationStateProvider;
public ReadinessProbeHealthIndicator(ApplicationAvailabilityProvider applicationAvailabilityProvider) {
this.applicationAvailabilityProvider = applicationAvailabilityProvider;
}
@Override
protected void doHealthCheck(Health.Builder builder) throws Exception {
if (ReadinessState.ready().equals(this.applicationStateProvider.getReadinessState())) {
if (ReadinessState.ready().equals(this.applicationAvailabilityProvider.getReadinessState())) {
builder.up();
}
else {

View File

@@ -0,0 +1,20 @@
/*
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Actuator support for application availability concerns.
*/
package org.springframework.boot.actuate.availability;

View File

@@ -14,14 +14,14 @@
* limitations under the License.
*/
package org.springframework.boot.actuate.kubernetes;
package org.springframework.boot.actuate.availability;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.boot.actuate.health.Status;
import org.springframework.boot.kubernetes.ApplicationStateProvider;
import org.springframework.boot.kubernetes.LivenessState;
import org.springframework.boot.availability.ApplicationAvailabilityProvider;
import org.springframework.boot.availability.LivenessState;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.BDDMockito.when;
@@ -34,13 +34,13 @@ import static org.mockito.Mockito.mock;
*/
class LivenessProbeHealthIndicatorTests {
private ApplicationStateProvider stateProvider;
private ApplicationAvailabilityProvider stateProvider;
private LivenessProbeHealthIndicator healthIndicator;
@BeforeEach
void setUp() {
this.stateProvider = mock(ApplicationStateProvider.class);
this.stateProvider = mock(ApplicationAvailabilityProvider.class);
this.healthIndicator = new LivenessProbeHealthIndicator(this.stateProvider);
}

View File

@@ -14,14 +14,14 @@
* limitations under the License.
*/
package org.springframework.boot.actuate.kubernetes;
package org.springframework.boot.actuate.availability;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.boot.actuate.health.Status;
import org.springframework.boot.kubernetes.ApplicationStateProvider;
import org.springframework.boot.kubernetes.ReadinessState;
import org.springframework.boot.availability.ApplicationAvailabilityProvider;
import org.springframework.boot.availability.ReadinessState;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.BDDMockito.when;
@@ -34,13 +34,13 @@ import static org.mockito.Mockito.mock;
*/
class ReadinessProbeHealthIndicatorTests {
private ApplicationStateProvider stateProvider;
private ApplicationAvailabilityProvider stateProvider;
private ReadinessProbeHealthIndicator healthIndicator;
@BeforeEach
void setUp() {
this.stateProvider = mock(ApplicationStateProvider.class);
this.stateProvider = mock(ApplicationAvailabilityProvider.class);
this.healthIndicator = new ReadinessProbeHealthIndicator(this.stateProvider);
}
@@ -51,8 +51,8 @@ class ReadinessProbeHealthIndicatorTests {
}
@Test
void readinessIsBusy() {
when(this.stateProvider.getReadinessState()).thenReturn(ReadinessState.busy());
void readinessIsUnready() {
when(this.stateProvider.getReadinessState()).thenReturn(ReadinessState.unready());
assertThat(this.healthIndicator.health().getStatus()).isEqualTo(Status.OUT_OF_SERVICE);
}