业务场景
需要对项目中的线程池指标进行监控检查
使用技术
Spring Actuate EndPoint
依赖如下
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>
配置如下
management:
endpoints:
web:
exposure:
include: '*'
endpoint:
health:
show-details: always
代码如下
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Executor;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
/**
* 线程池指标监控
* 访问地址: http://127.0.0.1/actuator/threadPoolEndpoint
* @author chunyang.leng
* @date 2022-09-20 4:57 PM
*/
@Component
@Endpoint(id = "threadPoolEndpoint")
public class ThreadPoolEndPoint {
@Autowired
private BeanFactory beanFactory;
@ReadOperation
public Map<String, Map<String,Number>> getMonitor(){
Map<String, Map<String,Number>> monitor = new HashMap<>(16);
if (beanFactory instanceof DefaultListableBeanFactory){
DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) beanFactory;
String[] beanNamesForType = defaultListableBeanFactory.getBeanNamesForType(Executor.class);
for (String beanName : beanNamesForType) {
Executor bean = defaultListableBeanFactory.getBean(beanName, Executor.class);
if (bean instanceof ThreadPoolExecutor ){
ThreadPoolExecutor threadPoolExecutor = (ThreadPoolExecutor) bean;
Map<String, Number> stringNumberMap = convThreadPoolExecutor(threadPoolExecutor);
monitor.put(beanName,stringNumberMap);
}
if (bean instanceof ThreadPoolTaskExecutor){
ThreadPoolTaskExecutor threadPoolTaskExecutor = (ThreadPoolTaskExecutor) bean;
ThreadPoolExecutor threadPoolExecutor = threadPoolTaskExecutor.getThreadPoolExecutor();
Map<String, Number> stringNumberMap = convThreadPoolExecutor(threadPoolExecutor);
monitor.put(beanName,stringNumberMap);
}
}
}
return monitor;
}
private Map<String,Number> convThreadPoolExecutor(ThreadPoolExecutor threadPoolExecutor){
Map<String,Number> data = new HashMap<>(16);
int activeCount = threadPoolExecutor.getActiveCount();
long completedTaskCount = threadPoolExecutor.getCompletedTaskCount();
long taskCount = threadPoolExecutor.getTaskCount();
int corePoolSize = threadPoolExecutor.getCorePoolSize();
int maximumPoolSize = threadPoolExecutor.getMaximumPoolSize();
int largestPoolSize = threadPoolExecutor.getLargestPoolSize();
BlockingQueue<Runnable> queue = threadPoolExecutor.getQueue();
if (Objects.nonNull(queue)){
int queueSize = queue.size();
data.put("queueSize",queueSize);
}
if (queue instanceof LinkedBlockingQueue){
LinkedBlockingQueue<Runnable> link = (LinkedBlockingQueue<Runnable>)queue;
int remainingCapacity = link.remainingCapacity();
data.put("remainingCapacity",remainingCapacity);
}
data.put("activeCount",activeCount);
data.put("completedTaskCount",completedTaskCount);
data.put("taskCount",taskCount);
data.put("corePoolSize",corePoolSize);
data.put("maximumPoolSize",maximumPoolSize);
data.put("largestPoolSize",largestPoolSize);
return data;
}
}