前言:XXL-Job作为一款轻量级的调度框架,在日常任务调度场景中应用广泛。提供了多种任务运行模式,覆盖Java,shell,Python,PHP等语言。提供了完善的任务监控机制,失败重试机制,任务告警机制。同时支持容器化部署,做到开箱即用。
本文,我们主要介绍如何在XXL-Job中集成企业微信告警功能。在xxl-job中默认提供了邮件告警,可以自行扩展钉钉,企业微信登告警方式。如果需要新增一种告警方式,需要自行新增一个 “com.xxl.job.admin.core.alarm.JobAlarm” 接口的告警实现。
首先我们需要再企业微信中申请一个机器人,获取机器人的webhook地址。因为在后续的告警中,我们需要调用机器人的webhook URL将告警信息通过机器人发送至我们的企微群中。
在xxl-job中,告警功能都是通过实现JobAlarm接口。
首先我们需要再 com.xxl.job.admin.core.model
包的XxlJobInfo类中,新增private String alarmWeChat;
的变量,并生成相应的getter,setter方法。供我们进行调用。
private String alarmWeChat; // 企微告警
public String getAlarmWeChat() {
return alarmWeChat;
}
public void setAlarmWeChat(String alarmWeChat) {
this.alarmWeChat = alarmWeChat;
}
我们在com.xxl.job.admin.core.alarm.impl
包中新定义一个企微告警类,用于实现JobAlarm接口。实现该接口后,我们需要重写接口中的doAlarm()方法。在以下代码中,我们在通过XxlJobInfo进行任务信息的获取,构建失败告警的内容,由于是不属于内网容器集群中,访问公网需要通过代理,所以我们这里直接构造失败告警信息(这里使用的是企微机器人的text格式消息。)与curl请求体(比较粗暴)。通过execCurl()方法进行失败告警信息的发送。
package com.xxl.job.admin.core.alarm.impl;
import com.alibaba.fastjson2.JSON;
import com.xxl.job.admin.core.alarm.JobAlarm;
import com.xxl.job.admin.core.model.XxlJobInfo;
import com.xxl.job.admin.core.model.XxlJobLog;
import com.xxl.job.core.biz.model.ReturnT;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.*;
import java.util.HashMap;
import java.util.Map;
@Component
public class WeChatJobAlarm implements JobAlarm {
@Value("${WEBHOOK_URL}")
private String WEBHOOK_URL;
private static Logger logger = LoggerFactory.getLogger(WeChatJobAlarm.class);
HttpHeaders headers = new HttpHeaders();
SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
RestTemplate restTemplate = new RestTemplate();
@Override
public boolean doAlarm(XxlJobInfo info, XxlJobLog jobLog) {
logger.info("开始调用失败任务ID");
boolean alarmResult = true;
if (logger != null && info.getAlarmWeChat() != null && info.getAlarmWeChat().trim().length() > 0) {
// 告警内容
String alarmMessage = "Failed Task ID: " + jobLog.getJobId();
if (jobLog.getTriggerCode() != ReturnT.SUCCESS_CODE) {
alarmMessage += "<br>TriggerMsg=<br>" + jobLog.getTriggerMsg();
}
if (jobLog.getHandleCode() > 0 && jobLog.getHandleCode() != ReturnT.SUCCESS_CODE) {
alarmMessage += "<br>HandleCode=" + jobLog.getHandleMsg();
}
//构造企微告警消息 new WeChatBotMessage(alarmMessage)
Map messageMap = new HashMap(8);
Map contentMap = new HashMap(8);
contentMap.put("content",alarmMessage);
messageMap.put("msgtype","text");
messageMap.put("text",contentMap);
String weChatMessage = JSON.toJSONString(messageMap);
String webhook = info.getAlarmWeChat();
//正式环境
String[] prUrl = {
"curl",
"-x",
"http://proxy-xxxx:1000",
"-H",
"Content-Type: application/json",
"POST",
webhook,
"-d",
weChatMessage
};
try {
execCurl(prUrl);
logger.info("企微告警发送成功。");
}catch (Exception e){
e.printStackTrace();
}
/* //发送告警信息
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<String> request = new HttpEntity<>(weChatMessage, headers);
ResponseEntity<String> response = restTemplate.postForEntity(webhook, request, String.class);
if (response.getStatusCode().is2xxSuccessful()) {
logger.info("机器人消息发送成功");
} else {
alarmResult = false;
logger.error("机器人消息发送失败");
}*/
}
return alarmResult;
}
public String execCurl(String[] cmds){
ProcessBuilder process = new ProcessBuilder(cmds);
Process p;
try {
p = process.start();
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
StringBuilder builder = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
builder.append(line);
builder.append(System.getProperty("line.separator"));
}
return builder.toString();
} catch (IOException e) {
logger.error("企微告警信息发送失败。");
e.printStackTrace();
}
return null;
}
}
至此,我们的消息发送部分就已经编写完成。但是我们的功能仍未完成。
当我们在创建任务时,需要对调度任务进行配置,我们需要将任务信息持久化到数据库中,同理我们新增的企微告警配置,关于企微机器人的webhook地址也需要进行持久化,索引我们还需要在XxlJobInfoMapper.xml文件中对我们的企微告警字段进行添加。
需要添加以下内容,以保证我们的企微告警地址能够被持久化到数据库中,在更新时也能够正常更新。
#在<resultMap></resultMap>部分添加以下内容
<resultMap id="XxlJobInfo" type="com.xxl.job.admin.core.model.XxlJobInfo" >
<result column="alarm_wechat" property="alarmWeChat" />
</resultMap>
#在<sql id="Base_Column_List"></sql>中添加以下内容
<sql id="Base_Column_List">
t.alarm_wechat
</sql>
#在insert与update语句块中,分别添加以下内容,以确保该字段能够被插入与更新
alarm_wechat, #{alarmWeChat}
后端部分开发完成后,我们还需要在前端页面上新增一个企微告警的入口,便于我们在创建任务,编辑任务时填入webhookURL。
xxl-job的页面主要由js进行开发。在jobinfo.index.1.js
文件中我们首先需要找到任务详情与更新部分的js代码。然后添加以下代码:
$("#updateModal .form input[name='alarmWeChat']").val( row.alarmWeChat );
$("#addModal .form input[name='alarmWeChat']").val( row.alarmWeChat );
xxl-job在启动时,需要再相应目录下创建日志文件。为了避免由于该问题导致启动失败,我们还需要在logback.xml
文件中将log.path修改为本地路径,便于我们进行本地进行调试。
工程启动后,我们在xxl-job主页进行任务的新增与更新。
我们可以看到在页面上我们的企微告警功能已经开发完成。我们手动触发任务后,并人工干预失败后,我们就可以再企业微信群收到任务失败的告警信息了。
至此,我们在xxl-job中的新增的企微告警功能就以开发完成。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。