序
本文主要研究一下springboot elasticsearch healthIndicator
ElasticsearchHealthIndicatorProperties
spring-boot-actuator-autoconfigure-2.1.4.RELEASE-sources.jar!/org/springframework/boot/actuate/autoconfigure/elasticsearch/ElasticsearchHealthIndicatorProperties.java
@ConfigurationProperties(prefix = "management.health.elasticsearch",
ignoreUnknownFields = false)
public class ElasticsearchHealthIndicatorProperties {
/**
* Comma-separated index names.
*/
private List<String> indices = new ArrayList<>();
/**
* Time to wait for a response from the cluster.
*/
private Duration responseTimeout = Duration.ofMillis(100);
public List<String> getIndices() {
return this.indices;
}
public void setIndices(List<String> indices) {
this.indices = indices;
}
public Duration getResponseTimeout() {
return this.responseTimeout;
}
public void setResponseTimeout(Duration responseTimeout) {
this.responseTimeout = responseTimeout;
}
}
复制代码
- ElasticsearchHealthIndicatorProperties提供了indices,responseTimeout两个配置项
ElasticSearchClientHealthIndicatorAutoConfiguration
spring-boot-actuator-autoconfigure-2.1.4.RELEASE-sources.jar!/org/springframework/boot/actuate/autoconfigure/elasticsearch/ElasticSearchClientHealthIndicatorAutoConfiguration.java
@Configuration
@ConditionalOnClass(Client.class)
@ConditionalOnBean(Client.class)
@ConditionalOnEnabledHealthIndicator("elasticsearch")
@AutoConfigureBefore(HealthIndicatorAutoConfiguration.class)
@AutoConfigureAfter(ElasticsearchAutoConfiguration.class)
@EnableConfigurationProperties(ElasticsearchHealthIndicatorProperties.class)
public class ElasticSearchClientHealthIndicatorAutoConfiguration extends
CompositeHealthIndicatorConfiguration<ElasticsearchHealthIndicator, Client> {
private final Map<String, Client> clients;
private final ElasticsearchHealthIndicatorProperties properties;
public ElasticSearchClientHealthIndicatorAutoConfiguration(
Map<String, Client> clients,
ElasticsearchHealthIndicatorProperties properties) {
this.clients = clients;
this.properties = properties;
}
@Bean
@ConditionalOnMissingBean(name = "elasticsearchHealthIndicator")
public HealthIndicator elasticsearchHealthIndicator() {
return createHealthIndicator(this.clients);
}
@Override
protected ElasticsearchHealthIndicator createHealthIndicator(Client client) {
Duration responseTimeout = this.properties.getResponseTimeout();
return new ElasticsearchHealthIndicator(client,
(responseTimeout != null) ? responseTimeout.toMillis() : 100,
this.properties.getIndices());
}
}
复制代码
- ElasticSearchClientHealthIndicatorAutoConfiguration创建的是ElasticsearchHealthIndicator(
elasticsearch
),它是通过org.elasticsearch.client.Client去检测的
ElasticsearchHealthIndicator
spring-boot-actuator-2.1.4.RELEASE-sources.jar!/org/springframework/boot/actuate/elasticsearch/ElasticsearchHealthIndicator.java
public class ElasticsearchHealthIndicator extends AbstractHealthIndicator {
private static final String[] ALL_INDICES = { "_all" };
private final Client client;
private final String[] indices;
private final long responseTimeout;
/**
* Create a new {@link ElasticsearchHealthIndicator} instance.
* @param client the Elasticsearch client
* @param responseTimeout the request timeout in milliseconds
* @param indices the indices to check
*/
public ElasticsearchHealthIndicator(Client client, long responseTimeout,
List<String> indices) {
this(client, responseTimeout,
(indices != null) ? StringUtils.toStringArray(indices) : null);
}
/**
* Create a new {@link ElasticsearchHealthIndicator} instance.
* @param client the Elasticsearch client
* @param responseTimeout the request timeout in milliseconds
* @param indices the indices to check
*/
public ElasticsearchHealthIndicator(Client client, long responseTimeout,
String... indices) {
super("Elasticsearch health check failed");
this.client = client;
this.responseTimeout = responseTimeout;
this.indices = indices;
}
@Override
protected void doHealthCheck(Health.Builder builder) throws Exception {
ClusterHealthRequest request = Requests.clusterHealthRequest(
ObjectUtils.isEmpty(this.indices) ? ALL_INDICES : this.indices);
ClusterHealthResponse response = this.client.admin().cluster().health(request)
.actionGet(this.responseTimeout);
switch (response.getStatus()) {
case GREEN:
case YELLOW:
builder.up();
break;
case RED:
default:
builder.down();
break;
}
builder.withDetail("clusterName", response.getClusterName());
builder.withDetail("numberOfNodes", response.getNumberOfNodes());
builder.withDetail("numberOfDataNodes", response.getNumberOfDataNodes());
builder.withDetail("activePrimaryShards", response.getActivePrimaryShards());
builder.withDetail("activeShards", response.getActiveShards());
builder.withDetail("relocatingShards", response.getRelocatingShards());
builder.withDetail("initializingShards", response.getInitializingShards());
builder.withDetail("unassignedShards", response.getUnassignedShards());
}
}
复制代码
- ElasticsearchHealthIndicator继承了AbstractHealthIndicator,这里如果不指定indices的话,默认是ALL_INDICES(
_all
);doHealthCheck方法使用client.admin().cluster().health(request)来进行请求,之后根据ClusterHealthResponse的状态来决定是up还是down,如果是GREEN或YELLOW则返回Status.UP,如果是RED则返回Status.DOWN
ElasticSearchRestHealthIndicatorAutoConfiguration
spring-boot-actuator-autoconfigure-2.1.4.RELEASE-sources.jar!/org/springframework/boot/actuate/autoconfigure/elasticsearch/ElasticSearchRestHealthIndicatorAutoConfiguration.java
@Configuration
@ConditionalOnClass(RestClient.class)
@ConditionalOnBean(RestClient.class)
@ConditionalOnEnabledHealthIndicator("elasticsearch")
@AutoConfigureBefore(HealthIndicatorAutoConfiguration.class)
@AutoConfigureAfter({ RestClientAutoConfiguration.class,
ElasticSearchClientHealthIndicatorAutoConfiguration.class })
public class ElasticSearchRestHealthIndicatorAutoConfiguration extends
CompositeHealthIndicatorConfiguration<ElasticsearchRestHealthIndicator, RestClient> {
private final Map<String, RestClient> clients;
public ElasticSearchRestHealthIndicatorAutoConfiguration(
Map<String, RestClient> clients) {
this.clients = clients;
}
@Bean
@ConditionalOnMissingBean(name = "elasticsearchRestHealthIndicator")
public HealthIndicator elasticsearchRestHealthIndicator() {
return createHealthIndicator(this.clients);
}
@Override
protected ElasticsearchRestHealthIndicator createHealthIndicator(RestClient client) {
return new ElasticsearchRestHealthIndicator(client);
}
}
复制代码
- ElasticSearchRestHealthIndicatorAutoConfiguration创建的是ElasticsearchRestHealthIndicator(
elasticsearchRest
),它是通过org.elasticsearch.client.RestClient去检测的
ElasticsearchRestHealthIndicator
spring-boot-actuator-2.1.4.RELEASE-sources.jar!/org/springframework/boot/actuate/elasticsearch/ElasticsearchRestHealthIndicator.java
public class ElasticsearchRestHealthIndicator extends AbstractHealthIndicator {
private static final String RED_STATUS = "red";
private final RestClient client;
private final JsonParser jsonParser;
public ElasticsearchRestHealthIndicator(RestClient client) {
super("Elasticsearch health check failed");
this.client = client;
this.jsonParser = JsonParserFactory.getJsonParser();
}
@Override
protected void doHealthCheck(Health.Builder builder) throws Exception {
Response response = this.client
.performRequest(new Request("GET", "/_cluster/health/"));
StatusLine statusLine = response.getStatusLine();
if (statusLine.getStatusCode() != HttpStatus.SC_OK) {
builder.down();
builder.withDetail("statusCode", statusLine.getStatusCode());
builder.withDetail("reasonPhrase", statusLine.getReasonPhrase());
return;
}
try (InputStream inputStream = response.getEntity().getContent()) {
doHealthCheck(builder,
StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8));
}
}
private void doHealthCheck(Health.Builder builder, String json) {
Map<String, Object> response = this.jsonParser.parseMap(json);
String status = (String) response.get("status");
if (RED_STATUS.equals(status)) {
builder.outOfService();
}
else {
builder.up();
}
builder.withDetails(response);
}
}
复制代码
- ElasticsearchRestHealthIndicator继承了AbstractHealthIndicator,构造器通过JsonParserFactory.getJsonParser()创建了JsonParser
- doHealthCheck方法通过RestClient.performRequest(new Request("GET", "/_cluster/health/"))进行请求,如果http response status code不是HttpStatus.SC_OK,直接返回Status.DOWN;如果是HttpStatus.SC_OK再进一步解析json判断
- 私有的doHealthCheck方法通过jsonParser.parseMap(json)解析返回json为Map,然后取status字段,如果是red则返回Status.OUT_OF_SERVICE,否则返回Status.UP
GET /_cluster/health/在http response status code为200的情况下返回的结构实例如下:
{
"cluster_name" : "docker-cluster",
"status" : "yellow",
"timed_out" : false,
"number_of_nodes" : 1,
"number_of_data_nodes" : 1,
"active_primary_shards" : 8,
"active_shards" : 8,
"relocating_shards" : 0,
"initializing_shards" : 0,
"unassigned_shards" : 6,
"delayed_unassigned_shards" : 0,
"number_of_pending_tasks" : 0,
"number_of_in_flight_fetch" : 0,
"task_max_waiting_in_queue_millis" : 0,
"active_shards_percent_as_number" : 57.14285714285714
}
复制代码
ElasticSearchJestHealthIndicatorAutoConfiguration
spring-boot-actuator-autoconfigure-2.1.4.RELEASE-sources.jar!/org/springframework/boot/actuate/autoconfigure/elasticsearch/ElasticSearchJestHealthIndicatorAutoConfiguration.java
@Configuration
@ConditionalOnClass(JestClient.class)
@ConditionalOnBean(JestClient.class)
@ConditionalOnEnabledHealthIndicator("elasticsearch")
@AutoConfigureBefore(HealthIndicatorAutoConfiguration.class)
@AutoConfigureAfter({ JestAutoConfiguration.class,
ElasticSearchClientHealthIndicatorAutoConfiguration.class })
public class ElasticSearchJestHealthIndicatorAutoConfiguration extends
CompositeHealthIndicatorConfiguration<ElasticsearchJestHealthIndicator, JestClient> {
private final Map<String, JestClient> clients;
public ElasticSearchJestHealthIndicatorAutoConfiguration(
Map<String, JestClient> clients) {
this.clients = clients;
}
@Bean
@ConditionalOnMissingBean(name = "elasticsearchHealthIndicator")
public HealthIndicator elasticsearchHealthIndicator() {
return createHealthIndicator(this.clients);
}
@Override
protected ElasticsearchJestHealthIndicator createHealthIndicator(JestClient client) {
return new ElasticsearchJestHealthIndicator(client);
}
}
复制代码
- ElasticSearchJestHealthIndicatorAutoConfiguration创建的是ElasticsearchJestHealthIndicator(
elasticsearch
),它是通过io.searchbox.client.JestClient去检测的
ElasticsearchJestHealthIndicator
spring-boot-actuator-2.1.4.RELEASE-sources.jar!/org/springframework/boot/actuate/elasticsearch/ElasticsearchJestHealthIndicator.java
public class ElasticsearchJestHealthIndicator extends AbstractHealthIndicator {
private final JestClient jestClient;
private final JsonParser jsonParser = JsonParserFactory.getJsonParser();
public ElasticsearchJestHealthIndicator(JestClient jestClient) {
super("Elasticsearch health check failed");
this.jestClient = jestClient;
}
@Override
protected void doHealthCheck(Health.Builder builder) throws Exception {
JestResult healthResult = this.jestClient
.execute(new io.searchbox.cluster.Health.Builder().build());
if (healthResult.getResponseCode() != 200 || !healthResult.isSucceeded()) {
builder.down();
builder.withDetail("statusCode", healthResult.getResponseCode());
}
else {
Map<String, Object> response = this.jsonParser
.parseMap(healthResult.getJsonString());
String status = (String) response.get("status");
if (status.equals(io.searchbox.cluster.Health.Status.RED.getKey())) {
builder.outOfService();
}
else {
builder.up();
}
builder.withDetails(response);
}
}
}
复制代码
- ElasticsearchJestHealthIndicator继承了AbstractHealthIndicator,构造器通过接收JestClient
- doHealthCheck方法通过jestClient.execute(new io.searchbox.cluster.Health.Builder().build())进行请求,如果http response status code不是200,或者healthResult.isSucceeded()不是true则直接返回Status.DOWN
- 如果http response status code是200且healthResult.isSucceeded()为true则再进一步通过jsonParser.parseMap(json)解析返回json为Map,然后取status字段,如果是io.searchbox.cluster.Health.Status.RED.getKey()则返回Status.OUT_OF_SERVICE,否则返回Status.UP
小结
- springboot提供了三个elasticsearch的healthIndicator配置,分别是ElasticSearchClientHealthIndicatorAutoConfiguration、ElasticSearchRestHealthIndicatorAutoConfiguration、ElasticSearchJestHealthIndicatorAutoConfiguration
- ElasticSearchClientHealthIndicatorAutoConfiguration创建的是ElasticsearchHealthIndicator(
elasticsearch
),它是通过org.elasticsearch.client.Client去检测的 - ElasticSearchRestHealthIndicatorAutoConfiguration创建的是ElasticsearchRestHealthIndicator(
elasticsearchRest
),它是通过org.elasticsearch.client.RestClient去检测的 - ElasticSearchJestHealthIndicatorAutoConfiguration创建的是ElasticsearchJestHealthIndicator(
elasticsearch
),它是通过io.searchbox.client.JestClient去检测的 - ElasticsearchHealthIndicatorProperties提供了indices,responseTimeout两个配置项,对于使用org.elasticsearch.client.Client的如果没有配置应用使用的indices,则使用ALL_INDICES(
_all
)去请求;而使用org.elasticsearch.client.RestClient或io.searchbox.client.JestClient的它们请求的是/_cluster/health/这个接口