feature: 开发线程池报警频率限制, 默认推送间隔五分钟(可通过配置修改).

pull/161/head
chen.ma 3 years ago
parent 3f8df895e0
commit 3ed2b32074

@ -0,0 +1,35 @@
package com.github.dynamic.threadpool.starter.alarm;
import lombok.Builder;
import lombok.Data;
/**
* .
*
* @author chen.ma
* @date 2021/10/28 22:15
*/
@Data
@Builder
public class AlarmControlDTO {
/**
* 线 Id
*/
private String threadPool;
/**
*
*/
private MessageTypeEnum typeEnum;
/**
* 线
*
* @return
*/
public String buildPk() {
return threadPool + "_" + typeEnum;
}
}

@ -0,0 +1,44 @@
package com.github.dynamic.threadpool.starter.alarm;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import java.util.concurrent.TimeUnit;
/**
* .
*
* @author chen.ma
* @date 2021/10/28 21:24
*/
public class AlarmControlHandler {
private final Cache<String, String> cache;
public AlarmControlHandler(long alarmInterval) {
cache = CacheBuilder.newBuilder()
.expireAfterWrite(alarmInterval, TimeUnit.MINUTES)
.build();
}
/**
* .
*
* @param alarmControl
* @return
*/
public boolean isSend(AlarmControlDTO alarmControl) {
String pkId = cache.getIfPresent(alarmControl.buildPk());
if (StrUtil.isBlank(pkId)) {
// val 无意义
cache.put(alarmControl.buildPk(), IdUtil.simpleUUID());
return true;
}
return false;
}
}

@ -14,8 +14,7 @@ import com.github.dynamic.threadpool.starter.toolkit.thread.RejectedTypeEnum;
import com.github.dynamic.threadpool.starter.wrap.DynamicThreadPoolWrap; import com.github.dynamic.threadpool.starter.wrap.DynamicThreadPoolWrap;
import com.google.common.base.Joiner; import com.google.common.base.Joiner;
import com.taobao.api.ApiException; import com.taobao.api.ApiException;
import lombok.NonNull; import lombok.AllArgsConstructor;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import java.util.List; import java.util.List;
@ -31,13 +30,13 @@ import java.util.concurrent.TimeUnit;
* @date 2021/8/15 15:49 * @date 2021/8/15 15:49
*/ */
@Slf4j @Slf4j
@RequiredArgsConstructor @AllArgsConstructor
public class DingSendMessageHandler implements SendMessageHandler { public class DingSendMessageHandler implements SendMessageHandler {
@NonNull
private String active; private String active;
@NonNull private Long alarmInterval;
private InstanceInfo instanceInfo; private InstanceInfo instanceInfo;
@Override @Override
@ -87,7 +86,7 @@ public class DingSendMessageHandler implements SendMessageHandler {
"<font color='#708090' size=2>拒绝策略:%s</font> \n\n" + "<font color='#708090' size=2>拒绝策略:%s</font> \n\n" +
"<font color='#708090' size=2>拒绝策略执行次数:</font><font color='#FF0000' size=2>%d</font> \n\n " + "<font color='#708090' size=2>拒绝策略执行次数:</font><font color='#FF0000' size=2>%d</font> \n\n " +
"<font color='#708090' size=2>OWNER@%s</font> \n\n" + "<font color='#708090' size=2>OWNER@%s</font> \n\n" +
"<font color='#708090' size=2>提示:5 分钟内此线程池不会重复告警(可配置)</font> \n\n" + "<font color='#708090' size=2>提示:%d 分钟内此线程池不会重复告警(可配置)</font> \n\n" +
" --- \n\n " + " --- \n\n " +
"**播报时间:%s**", "**播报时间:%s**",
@ -123,6 +122,8 @@ public class DingSendMessageHandler implements SendMessageHandler {
pool.getRejectCount(), pool.getRejectCount(),
// 告警手机号 // 告警手机号
afterReceives, afterReceives,
// 报警频率
alarmInterval,
// 当前时间 // 当前时间
DateUtil.now() DateUtil.now()
); );

@ -8,8 +8,24 @@ package com.github.dynamic.threadpool.starter.alarm;
*/ */
public enum MessageTypeEnum { public enum MessageTypeEnum {
/**
*
*/
CHANGE, CHANGE,
ALARM /**
*
*/
CAPACITY,
/**
*
*/
LIVENESS,
/**
*
*/
REJECT
} }

@ -19,12 +19,24 @@ import java.util.Optional;
@Slf4j @Slf4j
public class ThreadPoolAlarmManage { public class ThreadPoolAlarmManage {
/**
*
*/
private static final SendMessageService SEND_MESSAGE_SERVICE; private static final SendMessageService SEND_MESSAGE_SERVICE;
/**
*
*/
private static final AlarmControlHandler ALARM_CONTROL_HANDLER;
static { static {
SEND_MESSAGE_SERVICE = Optional.ofNullable(ApplicationContextHolder.getInstance()) SEND_MESSAGE_SERVICE = Optional.ofNullable(ApplicationContextHolder.getInstance())
.map(each -> each.getBean(MessageAlarmConfig.SEND_MESSAGE_BEAN_NAME, SendMessageService.class)) .map(each -> each.getBean(MessageAlarmConfig.SEND_MESSAGE_BEAN_NAME, SendMessageService.class))
.orElse(null); .orElse(null);
ALARM_CONTROL_HANDLER = Optional.ofNullable(ApplicationContextHolder.getInstance())
.map(each -> each.getBean(AlarmControlHandler.class))
.orElse(null);
} }
/** /**
@ -33,6 +45,9 @@ public class ThreadPoolAlarmManage {
* @param threadPoolExecutor * @param threadPoolExecutor
*/ */
public static void checkPoolCapacityAlarm(CustomThreadPoolExecutor threadPoolExecutor) { public static void checkPoolCapacityAlarm(CustomThreadPoolExecutor threadPoolExecutor) {
if (SEND_MESSAGE_SERVICE == null) {
return;
}
ThreadPoolAlarm threadPoolAlarm = threadPoolExecutor.getThreadPoolAlarm(); ThreadPoolAlarm threadPoolAlarm = threadPoolExecutor.getThreadPoolAlarm();
ResizableCapacityLinkedBlockIngQueue blockIngQueue = ResizableCapacityLinkedBlockIngQueue blockIngQueue =
(ResizableCapacityLinkedBlockIngQueue) threadPoolExecutor.getQueue(); (ResizableCapacityLinkedBlockIngQueue) threadPoolExecutor.getQueue();
@ -40,7 +55,9 @@ public class ThreadPoolAlarmManage {
int queueSize = blockIngQueue.size(); int queueSize = blockIngQueue.size();
int capacity = queueSize + blockIngQueue.remainingCapacity(); int capacity = queueSize + blockIngQueue.remainingCapacity();
int divide = CalculateUtil.divide(queueSize, capacity); int divide = CalculateUtil.divide(queueSize, capacity);
if (divide > threadPoolAlarm.getCapacityAlarm()) { boolean isSend = divide > threadPoolAlarm.getCapacityAlarm()
&& isSendMessage(threadPoolExecutor, MessageTypeEnum.CAPACITY);
if (isSend) {
SEND_MESSAGE_SERVICE.sendAlarmMessage(threadPoolExecutor); SEND_MESSAGE_SERVICE.sendAlarmMessage(threadPoolExecutor);
} }
} }
@ -52,13 +69,16 @@ public class ThreadPoolAlarmManage {
* @param threadPoolExecutor * @param threadPoolExecutor
*/ */
public static void checkPoolLivenessAlarm(boolean isCore, CustomThreadPoolExecutor threadPoolExecutor) { public static void checkPoolLivenessAlarm(boolean isCore, CustomThreadPoolExecutor threadPoolExecutor) {
if (isCore || SEND_MESSAGE_SERVICE == null) { if (isCore || SEND_MESSAGE_SERVICE == null || !isSendMessage(threadPoolExecutor, MessageTypeEnum.LIVENESS)) {
return; return;
} }
int activeCount = threadPoolExecutor.getActiveCount(); int activeCount = threadPoolExecutor.getActiveCount();
int maximumPoolSize = threadPoolExecutor.getMaximumPoolSize(); int maximumPoolSize = threadPoolExecutor.getMaximumPoolSize();
int divide = CalculateUtil.divide(activeCount, maximumPoolSize); int divide = CalculateUtil.divide(activeCount, maximumPoolSize);
if (divide > threadPoolExecutor.getThreadPoolAlarm().getLivenessAlarm()) {
boolean isSend = divide > threadPoolExecutor.getThreadPoolAlarm().getLivenessAlarm()
&& isSendMessage(threadPoolExecutor, MessageTypeEnum.CAPACITY);
if (isSend) {
SEND_MESSAGE_SERVICE.sendAlarmMessage(threadPoolExecutor); SEND_MESSAGE_SERVICE.sendAlarmMessage(threadPoolExecutor);
} }
} }
@ -69,7 +89,11 @@ public class ThreadPoolAlarmManage {
* @param threadPoolExecutor * @param threadPoolExecutor
*/ */
public static void checkPoolRejectAlarm(CustomThreadPoolExecutor threadPoolExecutor) { public static void checkPoolRejectAlarm(CustomThreadPoolExecutor threadPoolExecutor) {
if (SEND_MESSAGE_SERVICE != null) { if (SEND_MESSAGE_SERVICE == null) {
return;
}
if (isSendMessage(threadPoolExecutor, MessageTypeEnum.REJECT)) {
SEND_MESSAGE_SERVICE.sendAlarmMessage(threadPoolExecutor); SEND_MESSAGE_SERVICE.sendAlarmMessage(threadPoolExecutor);
} }
} }
@ -80,9 +104,26 @@ public class ThreadPoolAlarmManage {
* @param parameter * @param parameter
*/ */
public static void sendPoolConfigChange(PoolParameterInfo parameter) { public static void sendPoolConfigChange(PoolParameterInfo parameter) {
if (SEND_MESSAGE_SERVICE != null) { if (SEND_MESSAGE_SERVICE == null) {
SEND_MESSAGE_SERVICE.sendChangeMessage(parameter); return;
} }
SEND_MESSAGE_SERVICE.sendChangeMessage(parameter);
}
/**
* Is send message.
*
* @param threadPoolExecutor
* @param typeEnum
* @return
*/
private static boolean isSendMessage(CustomThreadPoolExecutor threadPoolExecutor, MessageTypeEnum typeEnum) {
AlarmControlDTO alarmControl = AlarmControlDTO.builder()
.threadPool(threadPoolExecutor.getThreadPoolId())
.typeEnum(typeEnum)
.build();
return ALARM_CONTROL_HANDLER.isSend(alarmControl);
} }
} }

@ -42,6 +42,11 @@ public class BootstrapProperties {
*/ */
private boolean banner = true; private boolean banner = true;
/**
* Alarm interval
*/
private Long alarmInterval;
/** /**
* notifys * notifys
*/ */

@ -1,16 +1,15 @@
package com.github.dynamic.threadpool.starter.config; package com.github.dynamic.threadpool.starter.config;
import com.github.dynamic.threadpool.common.model.InstanceInfo; import com.github.dynamic.threadpool.common.model.InstanceInfo;
import com.github.dynamic.threadpool.starter.alarm.BaseSendMessageService; import com.github.dynamic.threadpool.starter.alarm.*;
import com.github.dynamic.threadpool.starter.alarm.DingSendMessageHandler;
import com.github.dynamic.threadpool.starter.alarm.SendMessageHandler;
import com.github.dynamic.threadpool.starter.alarm.SendMessageService;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import org.apache.logging.log4j.util.Strings; import org.apache.logging.log4j.util.Strings;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.DependsOn; import org.springframework.context.annotation.DependsOn;
import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.core.env.ConfigurableEnvironment;
import java.util.Optional;
/** /**
* Message alarm config. * Message alarm config.
* *
@ -37,7 +36,14 @@ public class MessageAlarmConfig {
@Bean @Bean
public SendMessageHandler dingSendMessageHandler() { public SendMessageHandler dingSendMessageHandler() {
String active = environment.getProperty("spring.profiles.active", Strings.EMPTY); String active = environment.getProperty("spring.profiles.active", Strings.EMPTY);
return new DingSendMessageHandler(active, instanceInfo); Long alarmInterval = Optional.ofNullable(properties.getAlarmInterval()).orElse(5L);
return new DingSendMessageHandler(active, alarmInterval, instanceInfo);
}
@Bean
public AlarmControlHandler alarmControlHandler() {
Long alarmInterval = properties.getAlarmInterval();
return new AlarmControlHandler(alarmInterval);
} }
} }

@ -14,7 +14,8 @@ spring:
- type: DING - type: DING
url: https://oapi.dingtalk.com/robot/send?access_token= url: https://oapi.dingtalk.com/robot/send?access_token=
token: 4a582a588a161d6e3a1bd1de7eea9ee9f562cdfcbe56b6e72029e7fd512b2eae token: 4a582a588a161d6e3a1bd1de7eea9ee9f562cdfcbe56b6e72029e7fd512b2eae
receives: '15601166691,18210045950' receives: '15601166691'
alarm-interval: 5
server-addr: http://localhost:6691 server-addr: http://localhost:6691
namespace: prescription namespace: prescription
item-id: ${spring.application.name} item-id: ${spring.application.name}

Loading…
Cancel
Save