欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

spring boot的健康检查HealthIndicators实战

程序员文章站 2022-01-20 06:07:57
目录springboot 健康检查healthindicators自动配置的health indicator如何管理health indicatorredishealthindicator源码解析自定...

springboot 健康检查healthindicators

想提供自定义健康信息,你可以注册实现了healthindicator接口的spring beans。

你需要提供一个health()方法的实现,并返回一个health响应。

health响应需要包含一个status和可选的用于展示的详情。

import org.springframework.boot.actuate.health.healthindicator;
import org.springframework.stereotype.component;
@component
public class myhealth implements healthindicator {
@override
public health health() {
int errorcode = check(); // perform some specific health check
if (errorcode != 0) {
return health.down().withdetail("error code", errorcode).build();
} r
eturn health.up().build();
}
}

除了spring boot预定义的status类型,health也可以返回一个代表新的系统状态的自定义status。

在这种情况下,需要提供一个healthaggregator接口的自定义实现,或使用management.health.status.order属性配置默认的实现。

例如,假设一个新的,代码为fatal的status被用于你的一个healthindicator实现中。 为了配置严重程度, 你需要将下面的配

置添加到application属性文件中:

management.health.status.order: down, out_of_service, unknown, up

如果使用http访问health端点, 你可能想要注册自定义的status, 并使用healthmvcendpoint进行映射。 例如, 你可以将

fatal映射为httpstatus.service_unavailable。

springboot health indicator原理及其使用

作用

sping boot health 可以通过暴露的接口来提供系统及其系统组件是否可用。默认通过/health来访问。返回结果如下:

{
  "status": "up",
  "discoverycomposite": {
    "description": "spring cloud eureka discovery client",
    "status": "up",
    "discoveryclient": {
      "description": "spring cloud eureka discovery client",
      "status": "up",
      "services": [
        "..."
      ]
    },
    "eureka": {
      "description": "remote status from eureka server",
      "status": "up",
      "applications": {
        "aoms-mobile": 1,
        "data-exchange": 1,
        "cloud-gateway": 2,
        "aoms": 1,
        "aoms-aiis": 0,
        "aoms-eureka": 2
      }
    }
  },
  "diskspace": {
    "status": "up",
    "total": 313759301632,
    "free": 291947081728,
    "threshold": 10485760
  },
  "refreshscope": {
    "status": "up"
  },
  "hystrix": {
    "status": "up"
  }
}

状态说明:

  • unknown:未知状态,映射http状态码为503
  • up:正常,映射http状态码为200
  • down:失败,映射http状态码为503
  • out_of_service:不能对外提供服务,但是服务正常。映射http状态码为200

注意:unknown,down,out_of_service在为微服务环境下会导致注册中心中的实例也为down状态,请根据具体的业务来正确使用状态值。

自动配置的health indicator

自动配置的healthindicator主要有以下内容:

key name description
cassandra cassandradriverhealthindicator checks that a cassandra database is up.
couchbase couchbasehealthindicator checks that a couchbase cluster is up.
datasource datasourcehealthindicator checks that a connection to datasource can be obtained.
diskspace diskspacehealthindicator checks for low disk space.
elasticsearch elasticsearchresthealthindicator checks that an elasticsearch cluster is up.
hazelcast hazelcasthealthindicator checks that a hazelcast server is up.
influxdb influxdbhealthindicator checks that an influxdb server is up.
jms jmshealthindicator checks that a jms broker is up.
ldap ldaphealthindicator checks that an ldap server is up.
mail mailhealthindicator checks that a mail server is up.
mongo mongohealthindicator checks that a mongo database is up.
neo4j neo4jhealthindicator checks that a neo4j database is up.
ping pinghealthindicator always responds with up.
rabbit rabbithealthindicator checks that a rabbit server is up.
redis redishealthindicator checks that a redis server is up.
solr solrhealthindicator checks that a solr server is up.

分组

可以通过一个别名来启用一组指标的访问。配置的格式如下:

management.endpoint.health.group.<name>
//demo:
management.endpoint.health.group.mysys.include=db,redis,mail
management.endpoint.health.group.custom.exclude=rabbit

如何管理health indicator

开启

可以通过management.health.key.enabled来启用key对应的indicator。例如:

management.health.db.enabled=true

关闭

management.health.db.enabled=false

redishealthindicator源码解析

下面,通过redishealthindicator源码来为什么可以这么写。

代码结构

自动配置的health indicator有healthindicator和healthindicatorautoconfiguration两部分组成。

healthindicator所在包在org.springframework.boot.actuate,

healthindicatorautoconfiguration所在包在org.springframework.boot.actuate.autoconfigure下

spring boot的健康检查HealthIndicators实战

//redishealthindicator.java
public class redishealthindicator extends abstracthealthindicator {
	static final string version = "version";
	static final string redis_version = "redis_version";
	private final redisconnectionfactory redisconnectionfactory;
	public redishealthindicator(redisconnectionfactory connectionfactory) {
		super("redis health check failed");
		assert.notnull(connectionfactory, "connectionfactory must not be null");
		this.redisconnectionfactory = connectionfactory;
	}
	@override
	protected void dohealthcheck(health.builder builder) throws exception {
		redisconnection connection = redisconnectionutils
				.getconnection(this.redisconnectionfactory);
		try {
			if (connection instanceof redisclusterconnection) {
				clusterinfo clusterinfo = ((redisclusterconnection) connection)
						.clustergetclusterinfo();
				builder.up().withdetail("cluster_size", clusterinfo.getclustersize())
						.withdetail("slots_up", clusterinfo.getslotsok())
						.withdetail("slots_fail", clusterinfo.getslotsfail());
			}
			else {
				properties info = connection.info();
				builder.up().withdetail(version, info.getproperty(redis_version));
			}
		}
		finally {
			redisconnectionutils.releaseconnection(connection,
					this.redisconnectionfactory);
		}
	}
}

主要实现dohealthcheck方法来实现具体的判断逻辑。注意,操作完成后在finally中释放资源。

在父类abstracthealthindicator中,对dohealthcheck进行了try catch,如果出现异常,则返回down状态。

 //abstracthealthindicator.java
 @override
 public final health health() {
  health.builder builder = new health.builder();
  try {
   dohealthcheck(builder);
  }
  catch (exception ex) {
   if (this.logger.iswarnenabled()) {
    string message = this.healthcheckfailedmessage.apply(ex);
    this.logger.warn(stringutils.hastext(message) ? message : default_message,
      ex);
   }
   builder.down(ex);
  }
  return builder.build();
 }

redishealthindicatorautoconfiguration完成redishealthindicator的自动配置

@configuration
@conditionalonclass(redisconnectionfactory.class)
@conditionalonbean(redisconnectionfactory.class)
@conditionalonenabledhealthindicator("redis")
@autoconfigurebefore(healthindicatorautoconfiguration.class)
@autoconfigureafter({ redisautoconfiguration.class,
  redisreactivehealthindicatorautoconfiguration.class })
public class redishealthindicatorautoconfiguration extends
  compositehealthindicatorconfiguration<redishealthindicator, redisconnectionfactory> {
 private final map<string, redisconnectionfactory> redisconnectionfactories;
 public redishealthindicatorautoconfiguration(
   map<string, redisconnectionfactory> redisconnectionfactories) {
  this.redisconnectionfactories = redisconnectionfactories;
 }
 @bean
 @conditionalonmissingbean(name = "redishealthindicator")
 public healthindicator redishealthindicator() {
  return createhealthindicator(this.redisconnectionfactories);
 }
}

重点说明conditionalonenabledhealthindicator:如果management.health..enabled为true,则生效。

compositehealthindicatorconfiguration 中会通过healthindicatorregistry注册创建的healthindicator

自定义indicator

@component
@conditionalonproperty(name="spring.dfs.http.send-url")
@slf4j
public class dfshealthindicator implements healthindicator {
    @value("${spring.dfs.http.send-url}")
    private string dsfsendurl;
    @override
    public health health() {
        log.debug("正在检查dfs配置项...");
        log.debug("dfs 请求地址:{}",dsfsendurl);
        health.builder up = health.up().withdetail("url", dsfsendurl);
        try {
            httputils.telnet(stringutils.getipfromurl(dsfsendurl),stringutils.getportfromurl(dsfsendurl));
            return up.build();
        } catch (ioexception e) {
            e.printstacktrace();
            log.error("dfs配置项错误或网络超时");
            return up.withexception(e).build();
        }
    }
}

返回值:

{
    "dfs": {
    "status": "up",
    "url": "10.254.131.197:8088",
    "error": "java.net.connectexception: connection refused (connection refused)"
    }
}

以上为个人经验,希望能给大家一个参考,也希望大家多多支持。