Browse Source

限制钉钉消息发送数量

dev_shibei_match
jianjun 5 years ago
parent
commit
0f4a434bdd
  1. 33
      epmet-commons/epmet-commons-tools/src/main/java/com/epmet/commons/tools/dto/form/DingTalkTextMsg.java
  2. 29
      epmet-commons/epmet-commons-tools/src/main/java/com/epmet/commons/tools/filter/LogMsgSendFilter.java
  3. 185
      epmet-commons/epmet-commons-tools/src/main/java/com/epmet/commons/tools/utils/DingdingMsgSender.java
  4. 12
      epmet-module/data-statistical/data-statistical-server/src/main/java/com/epmet/controller/DemoController.java
  5. 2
      epmet-module/data-statistical/data-statistical-server/src/main/resources/logback-spring.xml

33
epmet-commons/epmet-commons-tools/src/main/java/com/epmet/commons/tools/dto/form/DingTalkTextMsg.java

@ -1,25 +1,32 @@
package com.epmet.commons.tools.dto.form; package com.epmet.commons.tools.dto.form;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import lombok.Data;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
import java.io.Serializable;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
/** /**
* desc: 钉钉文本消息参数 实体类 * desc: 钉钉文本消息参数 实体类
* date: 2019/2/20 11:00 *
* @date: 2020/6/29 9:06
* @author: jianjun liu * @author: jianjun liu
* email:liujianjun@yunzongnet.com * email:liujianjun@git.elinkit.com.cn
*/ */
public class DingTalkTextMsg { public class DingTalkTextMsg implements Serializable {
private static final long serialVersionUID = -3611771312188821915L;
/** /**
* 消息接收者 * 消息接收者
*/ */
private String receiver; private String webHook;
/**
* 密钥
*/
private String secret;
/** /**
* 发送内容 * 发送内容
*/ */
@ -35,12 +42,12 @@ public class DingTalkTextMsg {
*/ */
private boolean isAtAll; private boolean isAtAll;
public String getReceiver() { public String getWebHook() {
return receiver; return webHook;
} }
public void setReceiver(String receiver) { public void setWebHook(String webHook) {
this.receiver = receiver; this.webHook = webHook;
} }
public String getContent() { public String getContent() {
@ -67,6 +74,14 @@ public class DingTalkTextMsg {
isAtAll = atAll; isAtAll = atAll;
} }
public String getSecret() {
return secret;
}
public void setSecret(String secret) {
this.secret = secret;
}
public String getMsgContent() { public String getMsgContent() {
Map<String, Object> items = new HashMap<>(); Map<String, Object> items = new HashMap<>();
items.put("msgtype", "text"); items.put("msgtype", "text");

29
epmet-commons/epmet-commons-tools/src/main/java/com/epmet/commons/tools/filter/LogMsgSendFilter.java

@ -6,8 +6,9 @@ import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.classic.spi.IThrowableProxy; import ch.qos.logback.classic.spi.IThrowableProxy;
import ch.qos.logback.classic.spi.StackTraceElementProxy; import ch.qos.logback.classic.spi.StackTraceElementProxy;
import ch.qos.logback.core.spi.FilterReply; import ch.qos.logback.core.spi.FilterReply;
import com.epmet.commons.tools.utils.HttpClientManager; import com.epmet.commons.tools.dto.form.DingTalkTextMsg;
import com.epmet.commons.tools.utils.Result; import com.epmet.commons.tools.utils.DingdingMsgSender;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -21,6 +22,10 @@ import java.text.SimpleDateFormat;
*/ */
public class LogMsgSendFilter extends LevelFilter { public class LogMsgSendFilter extends LevelFilter {
private static final Logger logger = LoggerFactory.getLogger(LogMsgSendFilter.class); private static final Logger logger = LoggerFactory.getLogger(LogMsgSendFilter.class);
private DingdingMsgSender msgSender = new DingdingMsgSender();
private String webHook;
private String secret;
@Override @Override
public FilterReply decide(ILoggingEvent event) { public FilterReply decide(ILoggingEvent event) {
//如果日志级别等于设置的日志级别 则发送消息 //如果日志级别等于设置的日志级别 则发送消息
@ -43,9 +48,16 @@ public class LogMsgSendFilter extends LevelFilter {
IThrowableProxy throwableProxy = event.getThrowableProxy(); IThrowableProxy throwableProxy = event.getThrowableProxy();
//异常信息处理 暂时处理一级的5行数据 //异常信息处理 暂时处理一级的5行数据
apendStackInfo(stringBuilder, throwableProxy); apendStackInfo(stringBuilder, throwableProxy);
DingTalkTextMsg msg = new DingTalkTextMsg();
Result<String> flag = HttpClientManager.getInstance().sendAlarmMsg(stringBuilder.toString()); msg.setContent(stringBuilder.toString());
if (!flag.success()) { if (StringUtils.isNotBlank(webHook)) {
msg.setWebHook(webHook);
}
if (StringUtils.isNotBlank(secret)) {
msg.setSecret(secret);
}
boolean flag = msgSender.sendMsgAsync(msg);
if (!flag) {
logger.warn("msgSender.sendMsg fail,param:{}", stringBuilder.toString()); logger.warn("msgSender.sendMsg fail,param:{}", stringBuilder.toString());
} }
} catch (Exception e) { } catch (Exception e) {
@ -94,4 +106,11 @@ public class LogMsgSendFilter extends LevelFilter {
return dateFormat.format(timestamp); return dateFormat.format(timestamp);
} }
public void setWebHook(String webHook) {
this.webHook = webHook;
}
public void setSecret(String secret) {
this.secret = secret;
}
} }

185
epmet-commons/epmet-commons-tools/src/main/java/com/epmet/commons/tools/utils/DingdingMsgSender.java

@ -0,0 +1,185 @@
package com.epmet.commons.tools.utils;
import com.alibaba.fastjson.JSON;
import com.epmet.commons.tools.dto.form.DingTalkTextMsg;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.collect.Lists;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import javax.annotation.PreDestroy;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
/**
* desc: 发送消息工具类
*
* @date: 2020/6/29 8:43
* @author: jianjun liu
*/
@Component
public class DingdingMsgSender {
private final Logger logger = LoggerFactory.getLogger(DingdingMsgSender.class);
//如果不设置则为 开发环境机器人地址
private static final String webHook = "https://oapi.dingtalk.com/robot/send?access_token=90782b119f82a5b6bb8e0f819b6a77bbc2102b53aa2d7d2e24fa10b66d580b1c";
private static final String secret = "SEC080aac67ff78e79fdaba132aa51e3fb3f6060dec99492feaac82cabf9f8b6a19";
/**
* 默认10
*/
private static Integer maxQueueSize = 10;
/**
* 有序队列
*/
private ArrayBlockingQueue<DingTalkTextMsg> msgQueue = new ArrayBlockingQueue<>(maxQueueSize);
private volatile boolean running = false;
private Cache<String, AtomicInteger> limitCache = CacheBuilder.newBuilder().expireAfterWrite(1, TimeUnit.MINUTES).maximumSize(1000).build();
public DingdingMsgSender() {
}
private void handleMsg() {
DingTalkTextMsg msg = null;
try {
//阻塞取元素
msg = msgQueue.take();
if (msg != null) {
AtomicInteger limitCount = limitCache.getIfPresent(msg.getWebHook());
if (limitCount == null) {
limitCount = new AtomicInteger(1);
limitCache.put(msg.getWebHook(), limitCount);
}
if (limitCount.intValue() > maxQueueSize) {
msgQueue.offer(msg);
Thread.sleep(1000);
} else {
sendPostByJSON(msg);
limitCount.addAndGet(1);
}
} else {
Thread.sleep(1000);
}
} catch (Exception e) {
logger.warn("handleMsg exception,serverUrl:" + msg.getWebHook() + ",msg:" + JSON.toJSONString(msg), e);
}
}
/**
* desc:异步发送消息
*
* @param messageParam
* @return
* @throws IOException
*/
public boolean sendMsgAsync(DingTalkTextMsg messageParam) {
if (!running) {
running = true;
getThread().start();
}
boolean flag = false;
int currentQueueSize = msgQueue.size();
//非阻塞 添加/删除元素
if (currentQueueSize < maxQueueSize) {
flag = msgQueue.offer(messageParam);
} else {
msgQueue.poll();
DingTalkTextMsg param = new DingTalkTextMsg();
param.setContent("待发送消息队列已满,当前队列个数" + msgQueue.size() + "\n" + "最新消息内容:" + JSON.toJSONString(messageParam));
param.setWebHook(messageParam.getWebHook());
sendPostByJSON(param);
}
return flag;
}
/**
* 同步发送报警
*
* @param messageParam
* @return
* @throws IOException
*/
public Result<String> sendMsgSync(DingTalkTextMsg messageParam) {
return sendPostByJSON(messageParam);
}
private Thread getThread() {
Thread sendMsgThread = new Thread("MsgSender-Thread") {
@Override
public void run() {
while (running) {
handleMsg();
}
}
};
return sendMsgThread;
}
@PreDestroy
public void destroy() {
running = false;
}
/**
* 发送POST 请求
*
* @param param 请求参数JSON格式
* @return
*/
private Result<String> sendPostByJSON(DingTalkTextMsg param) {
if (StringUtils.isBlank(param.getWebHook())) {
param.setWebHook(webHook);
}
if (StringUtils.isBlank(param.getSecret())) {
param.setSecret(secret);
}
Result<String> result = new Result<String>().error();
Long timestamp = System.currentTimeMillis();
try {
String stringToSign = timestamp + "\n" + param.getSecret();
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(new SecretKeySpec(param.getSecret().getBytes("UTF-8"), "HmacSHA256"));
byte[] signData = mac.doFinal(stringToSign.getBytes("UTF-8"));
String sign = URLEncoder.encode(new String(Base64.encodeBase64(signData)), "UTF-8");
String url = param.getWebHook();
url = url.concat("&timestamp=" + timestamp + "&sign=" + sign);
String jsonStrParam = param.getMsgContent();
result = HttpClientManager.getInstance().sendPostByJSON(url, jsonStrParam);
} catch (Exception e) {
logger.warn("sendPostByJSON error", e);
}
return result;
}
public static void main(String[] args) {
for (int i = 0; i < 50; i++) {
DingTalkTextMsg dingTalkTextMsg = new DingTalkTextMsg();
dingTalkTextMsg.setWebHook("");
dingTalkTextMsg.setContent("测试消息" + i);
dingTalkTextMsg.setAtMobiles(Lists.newArrayList());
dingTalkTextMsg.setAtAll(false);
dingTalkTextMsg.setSecret("");
DingdingMsgSender msgSender = new DingdingMsgSender();
msgSender.sendMsgAsync(dingTalkTextMsg);
}
}
}

12
epmet-module/data-statistical/data-statistical-server/src/main/java/com/epmet/controller/DemoController.java

@ -2,20 +2,21 @@ package com.epmet.controller;
import com.epmet.dto.AgencySubTreeDto; import com.epmet.dto.AgencySubTreeDto;
import com.epmet.service.StatsDemoService; import com.epmet.service.StatsDemoService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.List;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future; import java.util.concurrent.Future;
import java.util.List;
@RequestMapping("demo") @RequestMapping("demo")
@RestController @RestController
@Slf4j
public class DemoController { public class DemoController {
@Autowired @Autowired
@ -24,6 +25,13 @@ public class DemoController {
@Autowired @Autowired
private ExecutorService executorService; private ExecutorService executorService;
@GetMapping("testAlarm")
public void testAlarm() {
for (int i = 0; i < 20; i++) {
log.error("测试消息"+i);
}
}
@GetMapping("testtx") @GetMapping("testtx")
public void testTx() { public void testTx() {
demoService.testTx(); demoService.testTx();

2
epmet-module/data-statistical/data-statistical-server/src/main/resources/logback-spring.xml

@ -130,6 +130,8 @@
<level>ERROR</level> <level>ERROR</level>
<onMatch>ACCEPT</onMatch> <onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch> <onMismatch>DENY</onMismatch>
<webHook>https://oapi.dingtalk.com/robot/send?access_token=90782b119f82a5b6bb8e0f819b6a77bbc2102b53aa2d7d2e24fa10b66d580b1c</webHook>
<secret>SEC080aac67ff78e79fdaba132aa51e3fb3f6060dec99492feaac82cabf9f8b6a19</secret>
</filter> </filter>
</appender> </appender>

Loading…
Cancel
Save