-
Notifications
You must be signed in to change notification settings - Fork 41.6k
Reactive Actuator
|
Note
|
We do have a reactor theme with a list of tasks/ideas.
|
Endpoints in the Actuator are defined by the Endpoint interface that has a simple invoke method that returns T. The purpose of such endpoint is to return some data that is then exposed higher in the stack to a client:
-
MvcEndpointexposes an endpoint to HTTP using Spring MVC -
JmxEndpointexposes an endpoint to JMX using Spring’s JMX facility
Both of those have a generic implementation that takes the endpoint and expose its data. While the JMX endpoint isn’t going to use any of the reactive feature, the HTTP endpoint in a reactive web application shouldn’t use MVC (simply as MVC isn’t expected to be on the classpath).
Also, most endpoints have additional features that are then exposed directly in the MVC and/or JMX layer. For instance, the logger endpoint allows to retrieve and change the level of a particular logger. With the support of reactive, we have an opportunity to review this architecture and provide a neutral layer that we adapt on the target environment. Ideally, each endpoint should be defined in this neutral layer.
The list of endpoints is available in the documentation.
Let’s have a look to each endpoint and figure out what it would take to make them reactive:
Audit events are backed by a repository. At the moment we only have an in memory implementation but it would be nice to have a ReactiveAuditEventRepository that provides a Flux<AuditEvent>.
The audit events endpoint is also a bit special as it doesn’t have a centralized Endpoint implementation. This can be a problem as having a third type of endpoint can lead to code duplication.
The auto-configuration report is available in memory so there isn’t a great need for a reactive based API for this.
The application context structure is available in memory so there isn’t a great need for a reactive based API for this.
The binding of ConfigurationProperties is available in memory so there isn’t a great need for a reactive based API for this.
dumpAllThreads has no reactive equivalent and is going to provide a List<ThreadInfo> so a reactive based API for this isn’t probably in order.
The environment is available in memory so there isn’t a great need for a reactive based API for this. This of course completely eludes PropertySource implementation that may use the network.
Flyway.info() builds a MigrationInfoService and call refresh() on it and that is a blocking API that is using JDBC behind the scenes.
The health endpoint is a perfect candidate for a reactive API. At the moment, an HealthIndicator has to implement the following API:
public interface HealthIndicator {
Health health();
}An alternative would be something along the lines of
public interface ReactiveHealthIndicator {
Mono<Health> health();
}We would need to zip all those Mono in a single one in order to compute the overall status. For that reason, we couldn’t stream the various entries that way since we need the global status to compute the relevant HTTP status.
The info endpoint invokes a configurable list of InfoContributor:
public interface ReactiveInfoContributor {
void contribute(Info.Builder builder);
}where Info.Builder allows to register key/value pairs. The value can be either a scalar value and then it will register a top-level value or the value can be a Map itself to register a "nested" namespace.
A reactive equivalent of this API could be as follows:
public interface ReactiveInfoContributor {
Flux<InfoEntry> contribute();
}where InfoEntry is a tuple of String and Object where Object can be a singular value or a nested map.
The logging information is available in memory so there isn’t a great need for a reactive based API for this.
The LiquibaseEndpoint is using a DataSource to retrieve the LiquibaseReport and that’s obviously blocking.
The list of MVC mappings are defined in the context so there is no need for a reactive API for this.
But we’d need to improve that endpoint to extract information of a router that has been defined programmatically. This is not currently possible, see SPR-15711.
Here’s a list of interesting work areas:
-
Provide a reactive-based API for the
healthendpoint and build an infrastructure to make it reactive -
Ditto for the
infoendpoint -
Find a way to identify the mappings that are defined by the new routeur API
-
Provide a way to stream web request details (
traceendpoint) -
Find a way to invoke blocking endpoints on a separate scheduler
-
Provide a way to stream the log file