Springboot Actuator的组件编写

Springboot Actuator的组件编写

前置说明

因为之前编写了redis-starter以及cache-starter, 然后最近有学习了springboot的actuator相关的知识,了解到springboot自己的spring-boot-starter-data-redis是有redis的健康状态监测的,然后spring-boot-starter-cache也有关于缓存命中的相关信息暴露,所以也想到了自己写的starter也加上相关的信息暴露并整合到springboot的actuator中进行暴露.

相关概念了解

  • RedisHealthIndicator
    这个就是spring-boot-starter-data-redis提供的关于redis健康检测信息提供类,待会儿我也会模仿写一个.

  • CacheStatisticsProvider,CacheStatistics
    这两个就是spring-boot-starter-cache提供的,一个是缓存信息的提供类,一个是spring提供的缓存统计持有类.

CustomRedisHealthIndicator编写

首先 可以参考以下spring自身对redis健康检测的实现RedisHealthIndicator

...
@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);
		}
	}
	...

可以看出其实主要是调用info接口来获取redis的信息,然后继续暴露.

我们继续模仿,如下面的代码所示

public class CustomRedisHealthIndicator extends AbstractHealthIndicator {
    @Autowired
    RedisUtil redisUtil;
    
    @Override
    protected void doHealthCheck(Health.Builder builder) throws Exception {
        try (Jedis jedis = redisUtil.getJedis()){
            String info = jedis.info();
            builder.up().withDetail("info", info);
        }
    }
}

这里简单的把info直接返回即可,然后将其进行自动装配,我们可以将自动装配的时间放到springboot的HealthIndicatorAutoConfiguration自动装配之前,这样可以确保我们的Indicator能被聚合进去,进行统一的展示, 代码如下

@AutoConfigureBefore(HealthIndicatorAutoConfiguration. class)
@Configuration
@ConditionalOnProperty(value = "redis.health", havingValue = "true")
public class CustomRedisHealthConfiguration {

    @Bean
    public CustomRedisHealthIndicator customRedisHealthIndicator(){
        return new CustomRedisHealthIndicator();
    }

}

CustomCachePublicMetrics编写

照理,还是先参考spring 的实现CachePublicMetrics

...
@Override
	public Collection<Metric<?>> metrics() {
		Collection<Metric<?>> metrics = new HashSet<Metric<?>>();
		for (Map.Entry<String, List<CacheManagerBean>> entry : getCacheManagerBeans()
				.entrySet()) {
				//添加信息
			addMetrics(metrics, entry.getKey(), entry.getValue()); 
		}
		return metrics;
	}

...
	private void addMetrics(Collection<Metric<?>> metrics, String cacheName,
			List<CacheManagerBean> cacheManagerBeans) {
		for (CacheManagerBean cacheManagerBean : cacheManagerBeans) {
			CacheManager cacheManager = cacheManagerBean.getCacheManager();
			Cache cache = unwrapIfNecessary(cacheManager.getCache(cacheName));
			//获取信息
			CacheStatistics statistics = getCacheStatistics(cache, cacheManager);
			if (statistics != null) {
				String prefix = cacheName;
				if (cacheManagerBeans.size() > 1) {
					prefix = cacheManagerBean.getBeanName() + "_" + prefix;
				}
				prefix = "cache." + prefix + (prefix.endsWith(".") ? "" : ".");
				metrics.addAll(statistics.toMetrics(prefix));
			}
		}
	}
	...
	@SuppressWarnings({ "rawtypes", "unchecked" })
	private CacheStatistics getCacheStatistics(Cache cache, CacheManager cacheManager) {
		if (this.statisticsProviders != null) {
			for (CacheStatisticsProvider provider : this.statisticsProviders) {
				Class<?> cacheType = ResolvableType
						.forClass(CacheStatisticsProvider.class, provider.getClass())
						.resolveGeneric();
				if (cacheType.isInstance(cache)) {
				   //获取信息
					CacheStatistics statistics = provider.getCacheStatistics(cacheManager,   
							cache);
					if (statistics != null) {
						return statistics;
					}
				}
			}
		}
		return null;
	}
	...

可以看到信息主要是从provider获取,随便看一个ConcurrentMapCacheStatisticsProvider

public class ConcurrentMapCacheStatisticsProvider
		implements CacheStatisticsProvider<ConcurrentMapCache> {

	@Override
	public CacheStatistics getCacheStatistics(CacheManager cacheManager,
			ConcurrentMapCache cache) {
		DefaultCacheStatistics statistics = new DefaultCacheStatistics();
		statistics.setSize((long) cache.getNativeCache().size());
		return statistics;
	}

}

因为我们实现的cache并没有用到spring的接口cacheManage和cache,所以就大概实现类似的功能如下

@AllArgsConstructor
public class CustomCacheStatistucsProvider {
    
    private CacheUtil cacheUtil;
    private CacheSupport cacheSupport;
    private CacheProperties cacheProperties;
    
    
    public CacheStatistics getCacheStatistics() {
        DefaultCacheStatistics statistics = new DefaultCacheStatistics();
        statistics.setSize((long) cacheUtil.size(cacheProperties.getPrefix() + "*")); //缓存个数
        double hitRatio = cacheSupport.getSuccess().doubleValue() / cacheSupport.getTotal().doubleValue(); 
        statistics.setHitRatio(hitRatio); //命中概率
        statistics.setMissRatio(1 - hitRatio); //未命中概率
        return statistics;
    }
    
}

然后创建一个暴露类

public class CustomCachePublicMetrics implements PublicMetrics {
    
    CustomCacheStatistucsProvider customCacheStatistucsProvider;
    
    
    @Override
    public Collection<Metric<?>> metrics() {
        CacheStatistics cacheStatistics = customCacheStatistucsProvider.getCacheStatistics();
        Collection<Metric<?>> metrics = cacheStatistics.toMetrics("cache.");
        return metrics;
    }
}

然后编写自动配置类,按照惯例其配置顺序在PublicMetricsAutoConfiguration之前

@AutoConfigureBefore(PublicMetricsAutoConfiguration.class)
@Configuration
@ConditionalOnProperty("cache.metric")
public class CustomCachePublicMetricsConfiguration {
    
    @Bean
    public CustomCacheStatistucsProvider customCacheStatistucsProvider(){
        return new CustomCacheStatistucsProvider();
    }
    
    @Bean
    public CustomCachePublicMetrics customCachePublicMetrics(){
        return new CustomCachePublicMetrics();
    }

}

这样我们的代码就基本编写完毕了.别忘了在spring.factories加上相关的配置类.

查看结果

在这里插入图片描述

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值