当前位置: 首页 > article >正文

【JAVA】利用钉钉自定义机器人监控NACOS服务,实现实时下线通知

利用钉钉自定义机器人监控NACOS服务,实现实时下线通知

自定义机器人步骤

  1. 创建一个钉钉群,拉人创建
  2. 在群设置中,选择自定义机器人
  3. 记住webhook 和 accessKey,用于代码中配置

钉钉实体类

@Data
public class MessageSender {
    // 消息类型
    private String messageType;
    // 钉钉的 webhook URL
    private String webhookUrl;
    // 安全密钥
    private String accessKey;
    // 消息内容
    private String messageContent;
    // 指定的接收者手机号列表
    private List<String> recipientMobiles;
    // 是否发送给所有人
    private boolean notifyAll;
}

监控代码

@Component
public class ServiceStatusMonitor {
    private static final Logger logger = LoggerFactory.getLogger(ServiceStatusMonitor.class);

    @Value("${dingtalk.webhook}")
    private String webhook;

    @Value("${dingtalk.secret}")
    private String secret;

    @Value("${dingtalk.userMobil}")
    private String[] userMobil;

    @Value("${dingtalk.namespace}")
    private String namespace;

    @Value("${spring.cloud.nacos.config.server-addr}")
    private String nacosUrl;

    private static Map<String, Integer> instanceCache = new ConcurrentHashMap<>();

    // 初始化服务监控
    @PostConstruct
    public void initialize() throws Exception {
        List<String> mobileList = Arrays.asList(userMobil);

        Properties properties = System.getProperties();
        properties.setProperty("serverAddr", nacosUrl);
        properties.setProperty("namespace", namespace);
        NamingService namingService = NamingFactory.createNamingService(properties);
        
        List<String> monitoredServices = Arrays.asList("order", "serviceA", "serviceB"); // 监控的服务列表
        
        for (String serviceName : monitoredServices) {
            namingService.subscribe(serviceName, event -> {
                List<Instance> instances = ((NamingEvent) event).getInstances();
                
                instanceCache.computeIfAbsent(serviceName, k -> instances.size());
                
                if (instances.size() < instanceCache.get(serviceName)) {
                    MessageSender alertMessage = new MessageSender();
                    alertMessage.setNotifyAll(false);
                    alertMessage.setMessageType("text");
                    alertMessage.setAccessKey(secret);
                    alertMessage.setWebhookUrl(webhook);
                    alertMessage.setRecipientMobiles(mobileList);
                    alertMessage.setMessageContent(serviceName + " 服务下线,当前在线节点数:" + instances.size());
                    
                    DingTalkUtil.sendMessage(alertMessage);
                    logger.info("服务下线: " + serviceName);
                    instanceCache.put(serviceName, instances.size());
                } else {
                    logger.info("服务上线: " + serviceName + ", 当前在线节点数:" + instances.size());
                }
            });
        }
    }
}

封装工具类

public class DingTalkUtils {
    private static final Logger logger = LoggerFactory.getLogger(DingTalkUtils.class);
    // 消息类型常量
    private static final String MESSAGE_TYPE_TEXT = "text";

    /**
     * 发送钉钉消息
     **/
    public static void sendMessage(MessageSender message) {
        try {
            logger.info("准备发送钉钉消息:" + message);
            Long timestamp = System.currentTimeMillis();
            String secret = message.getAccessKey();

            String signatureString = timestamp + "\n" + secret;
            Mac mac = Mac.getInstance("HmacSHA256");
            mac.init(new SecretKeySpec(secret.getBytes("UTF-8"), "HmacSHA256"));
            byte[] signedData = mac.doFinal(signatureString.getBytes("UTF-8"));
            String signature = URLEncoder.encode(new String(Base64.encodeBase64(signedData)), "UTF-8");

            DingTalkClient client = new DefaultDingTalkClient(message.getWebhookUrl() + "&timestamp=" + timestamp + "&sign=" + signature);
            OapiRobotSendRequest request = new OapiRobotSendRequest();

            OapiRobotSendRequest.At at = new OapiRobotSendRequest.At();
            if (message.isNotifyAll() || message.getRecipientMobiles() == null || message.getRecipientMobiles().isEmpty()) {
                // 发送给所有人
                at.setIsAtAll(true);
            } else {
                // 发送给指定用户
                at.setAtMobiles(message.getRecipientMobiles());
                at.setIsAtAll(false);
            }
            request.setAt(at);

            // 处理文本消息
            if (MESSAGE_TYPE_TEXT.equals(message.getMessageType())) {
                request.setMsgtype(MESSAGE_TYPE_TEXT);
                OapiRobotSendRequest.Text text = new OapiRobotSendRequest.Text();
                text.setContent(message.getMessageContent());
                request.setText(text);
            }

            OapiRobotSendResponse response = client.execute(request);
            logger.info("钉钉消息发送结果:" + response);
        } catch (Exception e) {
            logger.error("钉钉消息发送异常", e);
        }
    }

    public static void main(String[] args) {
        List<String> mobileList = new ArrayList<>();
        mobileList.add("13026578156");

        MessageSender message = new MessageSender();
        message.setMessageType(MESSAGE_TYPE_TEXT);
        message.setNotifyAll(false);
        message.setRecipientMobiles(mobileList);
        message.setWebhookUrl("https://oapi.dingtalk.com/robot/send?access_token=a4dxxxxxxxxxxxx347e4b1267dd4f39");
        message.setAccessKey("SECe4f7ef42exxxxxxxxxxxxxxxxxxxxxxx07d07287769f16c91d");
        message.setMessageContent("监控消息通知");
        sendMessage(message);
    }
}


yml配置

#钉钉消息推送
dingtalk:
  webhook: https://oapi.dingtalk.com/robot/send?access_token=a4dab6098cf65xxxxxxxxxxxxxxxxxxxb1267dd4f39
  secret: SECe4f7ef42ea7d10df102xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx07287769f16c91d
  userMobil: 1xxxxxx156
  namespace: dev

钉钉依赖

    <!--钉钉消息推送依赖-->
        <dependency>
            <groupId>com.aliyun</groupId>
            <artifactId>alibaba-dingtalk-service-sdk</artifactId>
            <version>2.0.0</version>
            <exclusions>
                <exclusion>
                    <groupId>log4j</groupId>
                    <artifactId>log4j</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

http://www.kler.cn/a/377727.html

相关文章:

  • 机器视觉检测相机基础知识 | 颜色 | 光源 | 镜头 | 分辨率 / 精度 / 公差
  • Python PyMupdf 去除PDF文档中Watermark标识水印
  • 只谈C++11新特性 - 默认函数
  • 微信小程序 不同角色进入不同页面、呈现不同底部导航栏
  • 产品初探Devops!以及AI如何赋能Devops?
  • 初始 ShellJS:一个 Node.js 命令行工具集合
  • LabVIEW 离心泵机组故障诊断系统
  • 【elkb】创建用户和角色
  • 银行零售贵金属交易-小程序端业务
  • 项目升级到.Net8.0 Autofac引发诡异的问题
  • Rust常用属性及应用
  • windows rdp 将远程技术嵌入到你的软件——未来之窗行业应用跨平台架构
  • 社区交流系统设计与实现
  • JDS汽车售后检测在车联网系统中的定位
  • buuctf
  • Android编译环境构建(二)(可用于物理机、虚拟机、容器化Jenkins环境)
  • 梁山派入门指南4——定时器使用详解,包括定时器中断、PWM产生、输入捕获测量频率
  • Java面试经典 150 题.P27. 移除元素(002)
  • 服务器上清理Docker容器运行日志的正确方法
  • tauri开发中如果取消了默认的菜单项,复制黏贴撤销等功能也就没有了,解决办法
  • 系统性能测试笔记-JMeter性能测试
  • 力扣(leetcode)题目总结——字符串篇
  • Zookeeper 和 Eureka 做注册中心有什么区别?
  • 基于JavaWeb+MySQL实现口算题卡
  • 服务器的免密登录和文件传输
  • 区块链-C++挖矿软件XMRIG源码分析