Health checks

Akka Management supports two kinds of health checks:

  • Readiness checks: should the application receive external traffic, for example waiting for the following to complete
    • Joining a Cluster
    • Establishing a connection to a database or queuing system
  • Liveness checks: should the application be left running

Readiness checks can be used to decide if a load balancer should route traffic whereas liveness checks can be used in environments which can restart a hung process.

This matches Kubernetes Health checks. See Kubernetes Liveness and Readiness Probes: How to Avoid Shooting Yourself in the Foot for a good overview of how to use readiness and liveness probes.

Akka Management provides endpoints for readiness and liveness checks out of the box at /ready and /alive (paths can be configured, see below). Configuration settings are used to add checks to back those endpoints. When called, each endpoint will only report to be healthy when all the configured health checks (for the particular kind, readiness or liveness) are succeeding.

Defining a Health Check

A health check must extend Function0[Future[Boolean]]Supplier[CompletionStage[Boolean]] and have either a no argument constructor or a constructor with a single argument of type ActorSystem. A general type is used rather than a specific interface so that modules such as akka-cluster can provide health checks without depending on Akka management.

Having access to the ActorSystem allows loading of any external resource via an Akka extension e.g. Cluster or a database connection. Health checks return a FutureCompletionStage so that an asynchronous action can be taken.

Scala
class ExampleHealthCheck(system: ActorSystem) extends (() => Future[Boolean]) {
  override def apply(): Future[Boolean] = {
    Future.successful(true)
  }
}
Java
public class BasicHealthCheck implements Supplier<CompletionStage<Boolean>> {

    public BasicHealthCheck(ActorSystem system) {
    }

    @Override
    public CompletionStage<Boolean> get() {
        return CompletableFuture.completedFuture(true);
    }
}

Typically the ActorSystem is used to get a hold of any state needed to execute the check e.g.

Scala
class ClusterHealthCheck(system: ActorSystem) extends (() => Future[Boolean]) {
  private val cluster = Cluster(system)
  override def apply(): Future[Boolean] = {
    Future.successful(cluster.selfMember.status == MemberStatus.Up)
  }
}
Java
class ClusterCheck implements Supplier<CompletionStage<Boolean>> {

    private final Cluster cluster;

    public ClusterCheck(ActorSystem system) {
        cluster = Cluster.get(system);
    }

    @Override
    public CompletionStage<Boolean> get() {
        return CompletableFuture.completedFuture(cluster.selfMember().status() == MemberStatus.up());
    }
}

Note that Cluster Http Management includes a health check for cluster membership that is configurable for which states are considered healthy.

Any of the above health checks can be configured as either readiness checks or liveness checks.

Configuring health checks

Health checks are picked up from configuration. Modules are expected to provide health checks e.g. Cluster Http Management provides a cluster readiness check.

Application specific health checks can be added a name = <fully qualified class name> to akka.management.health-checks.readiness-checks or akka.management.health-checks.liveness-checks e.g.

akka.management {
  health-checks {
    readiness-checks {
      # Default health check for cluster. Overwrite the setting to replace it with
      # your implementation or set it to "" (empty string) to disable this check.
      cluster-membership = "akka.management.cluster.scaladsl.ClusterMembershipCheck"
    }
  }
}

Hosting health checks as an Akka Management Route

Health checks can be hosted via the Akka management HTTP server. The akka.management.HealthCheckRoutes is enabled by default as an Akka management route provider.

By default all readiness checks are hosted on /ready and liveness checks are hosted on /alive. If all of the checks for an endpoint succeed a 200 is returned, if any fail or return false a 500 is returned. The paths are configurable via akka.management.health-checks.readiness-path and akka.management.health-checks.liveness-path e.g.

akka.management.health-checks {
  readiness-path = "health/ready"
  liveness-path = "health/alive"
}

The akka.management.HealthCheckRoutes can be disabled with the following configuration but that also means that the configured readiness-checks and liveness-checks will not be used.

akka.management.http.routes {
  health-checks = ""
}
Found an error in this documentation? The source code for this page can be found here. Please feel free to edit and contribute a pull request.