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

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

自定义机器人步骤

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

钉钉实体类

java 复制代码
@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;
}

监控代码

java 复制代码
@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());
                }
            });
        }
    }
}

封装工具类

java 复制代码
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配置

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

钉钉依赖

java 复制代码
    <!--钉钉消息推送依赖-->
        <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>
相关推荐
东阳马生架构25 分钟前
订单初版—5.售后退货链路中的技术问题说明文档
java
小小寂寞的城30 分钟前
JAVA策略模式demo【设计模式系列】
java·设计模式·策略模式
JAVA学习通1 小时前
图书管理系统(完结版)
java·开发语言
xiyuping241 小时前
ROS1学习第二弹
学习·机器人
abigalexy1 小时前
深入Java锁机制
java
paishishaba1 小时前
处理Web请求路径参数
java·开发语言·后端
神仙别闹1 小时前
基于Java+MySQL实现(Web)可扩展的程序在线评测系统
java·前端·mysql
程序无bug1 小时前
Java中的8中基本数据类型转换
java·后端
雪球工程师团队1 小时前
代码“蝴蝶效应”终结者:AI Review + AST 联展,构建智能测试防御新体系
java·ai编程·测试
你喜欢喝可乐吗?1 小时前
RuoYi-Cloud ruoyi-gateway 网关模块
java·spring cloud·gateway