quartz监控日志(一)

quartz监控日志(二)添加监听器

quartz监控日志(三)查看卡死线程堆栈

上面几章介绍了quartz监控的几种方式,下面再介绍一种监听方式:自定义QuartzJobBean

一、自定义QuartzJobBean


/**
* 定时任务处理
*
* @author lipeng
*
*/
@DisallowConcurrentExecution
public class ScheduleJob extends QuartzJobBean
{
private static final Logger log = LoggerFactory.getLogger(ScheduleJob.class); private ThreadPoolTaskExecutor executor = SpringUtils.getBean("threadPoolTaskExecutor"); private final static ISysJobLogService jobLogService = SpringUtils.getBean(ISysJobLogService.class); @Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException
{
SysJob job = new SysJob();
BeanUtils.copyBeanProp(job, context.getMergedJobDataMap().get(ScheduleConstants.TASK_PROPERTIES)); SysJobLog jobLog = new SysJobLog();
jobLog.setJobName(job.getJobName());
jobLog.setJobGroup(job.getJobGroup());
jobLog.setMethodName(job.getMethodName());
jobLog.setMethodParams(job.getMethodParams());
jobLog.setCreateTime(new Date()); long startTime = System.currentTimeMillis(); try
{
// 执行任务
log.info("任务开始执行 - 名称:{} 方法:{}", job.getJobName(), job.getMethodName());
ScheduleRunnable task = new ScheduleRunnable(job.getJobName(), job.getMethodName(), job.getMethodParams());
Future<?> future = executor.submit(task);
future.get();
long times = System.currentTimeMillis() - startTime;
// 任务状态 0:成功 1:失败
jobLog.setStatus(Constants.SUCCESS);
jobLog.setJobMessage(job.getJobName() + " 总共耗时:" + times + "毫秒"); log.info("任务执行结束 - 名称:{} 耗时:{} 毫秒", job.getJobName(), times);
}
catch (Exception e)
{
log.info("任务执行失败 - 名称:{} 方法:{}", job.getJobName(), job.getMethodName());
log.error("任务执行异常 - :", e);
long times = System.currentTimeMillis() - startTime;
jobLog.setJobMessage(job.getJobName() + " 总共耗时:" + times + "毫秒");
// 任务状态 0:成功 1:失败
jobLog.setStatus(Constants.FAIL);
jobLog.setExceptionInfo(StringUtils.substring(e.getMessage(), 0, 2000));
}
finally
{
jobLogService.addJobLog(jobLog);
}
}
}

SysJobLog


/**
* 定时任务调度日志表 sys_job_log
*
* @author lipeng
*/
public class SysJobLog extends BaseEntity
{
private static final long serialVersionUID = 1L; /** ID */
@Excel(name = "日志序号")
private Long jobLogId; /** 任务名称 */
@Excel(name = "任务名称")
private String jobName; /** 任务组名 */
@Excel(name = "任务组名")
private String jobGroup; /** 任务方法 */
@Excel(name = "任务方法")
private String methodName; /** 方法参数 */
@Excel(name = "方法参数")
private String methodParams; /** 日志信息 */
@Excel(name = "日志信息")
private String jobMessage; /** 执行状态(0正常 1失败) */
@Excel(name = "执行状态", readConverterExp = "0=正常,1=失败")
private String status; /** 异常信息 */
@Excel(name = "异常信息")
private String exceptionInfo; public Long getJobLogId()
{
return jobLogId;
} public void setJobLogId(Long jobLogId)
{
this.jobLogId = jobLogId;
} public String getJobName()
{
return jobName;
} public void setJobName(String jobName)
{
this.jobName = jobName;
} public String getJobGroup()
{
return jobGroup;
} public void setJobGroup(String jobGroup)
{
this.jobGroup = jobGroup;
} public String getMethodName()
{
return methodName;
} public void setMethodName(String methodName)
{
this.methodName = methodName;
} public String getMethodParams()
{
return methodParams;
} public void setMethodParams(String methodParams)
{
this.methodParams = methodParams;
} public String getJobMessage()
{
return jobMessage;
} public void setJobMessage(String jobMessage)
{
this.jobMessage = jobMessage;
} public String getStatus()
{
return status;
} public void setStatus(String status)
{
this.status = status;
} public String getExceptionInfo()
{
return exceptionInfo;
} public void setExceptionInfo(String exceptionInfo)
{
this.exceptionInfo = exceptionInfo;
} @Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("jobLogId", getJobLogId())
.append("jobName", getJobName())
.append("jobGroup", getJobGroup())
.append("methodName", getMethodName())
.append("methodParams", getMethodParams())
.append("jobMessage", getJobMessage())
.append("status", getStatus())
.append("exceptionInfo", getExceptionInfo())
.append("createTime", getCreateTime())
.toString();
}
}

ScheduleRunnable


/**
* 执行定时任务
*
* @author lipeng
*
*/
public class ScheduleRunnable implements Runnable
{
private static final Logger log = LoggerFactory.getLogger(ScheduleRunnable.class); private Object target;
private Method method;
private String params; public ScheduleRunnable(String beanName, String methodName, String params)
throws NoSuchMethodException, SecurityException
{
this.target = SpringUtils.getBean(beanName);
this.params = params; if (StringUtils.isNotEmpty(params))
{
this.method = target.getClass().getDeclaredMethod(methodName, String.class);
}
else
{
this.method = target.getClass().getDeclaredMethod(methodName);
}
} @Override
public void run()
{
try
{
ReflectionUtils.makeAccessible(method);
if (StringUtils.isNotEmpty(params))
{
method.invoke(target, params);
}
else
{
method.invoke(target);
}
}
catch (Exception e)
{
log.error("执行定时任务 - :", e);
}
}
}

二、创建job

  /**
* 创建定时任务
*/
public static void createScheduleJob(Scheduler scheduler, SysJob job)
{
try
{
// 构建job信息
JobDetail jobDetail = JobBuilder.newJob(ScheduleJob.class).withIdentity(getJobKey(job.getJobId())).build(); // 表达式调度构建器
CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCronExpression());
cronScheduleBuilder = handleCronScheduleMisfirePolicy(job, cronScheduleBuilder); // 按新的cronExpression表达式构建一个新的trigger
CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(getTriggerKey(job.getJobId()))
.withSchedule(cronScheduleBuilder).build(); // 放入参数,运行时的方法可以获取
jobDetail.getJobDataMap().put(ScheduleConstants.TASK_PROPERTIES, job); scheduler.scheduleJob(jobDetail, trigger); // 暂停任务
if (job.getStatus().equals(ScheduleConstants.Status.PAUSE.getValue()))
{
pauseJob(scheduler, job.getJobId());
}
}
catch (SchedulerException e)
{
log.error("createScheduleJob 异常:", e);
}
catch (TaskException e)
{
log.error("createScheduleJob 异常:", e);
}
}

三、将数据库中的job初始化

 /**
* 项目启动时,初始化定时器
*/
@PostConstruct
public void init()
{
List<SysJob> jobList = jobMapper.selectJobAll();
for (SysJob job : jobList)
{
CronTrigger cronTrigger = ScheduleUtils.getCronTrigger(scheduler, job.getJobId());
// 如果不存在,则创建
if (cronTrigger == null)
{
ScheduleUtils.createScheduleJob(scheduler, job);
}
else
{
ScheduleUtils.updateScheduleJob(scheduler, job);
}
}
}

ScheduleUtils源代码如下:


/**
* 定时任务工具类
*
* @author lipeng
*
*/
public class ScheduleUtils
{
private static final Logger log = LoggerFactory.getLogger(ScheduleUtils.class); /**
* 获取触发器key
*/
public static TriggerKey getTriggerKey(Long jobId)
{
return TriggerKey.triggerKey(ScheduleConstants.TASK_CLASS_NAME + jobId);
} /**
* 获取jobKey
*/
public static JobKey getJobKey(Long jobId)
{
return JobKey.jobKey(ScheduleConstants.TASK_CLASS_NAME + jobId);
} /**
* 获取表达式触发器
*/
public static CronTrigger getCronTrigger(Scheduler scheduler, Long jobId)
{
try
{
return (CronTrigger) scheduler.getTrigger(getTriggerKey(jobId));
}
catch (SchedulerException e)
{
log.error("getCronTrigger 异常:", e);
}
return null;
} /**
* 创建定时任务
*/
public static void createScheduleJob(Scheduler scheduler, SysJob job)
{
try
{
// 构建job信息
JobDetail jobDetail = JobBuilder.newJob(ScheduleJob.class).withIdentity(getJobKey(job.getJobId())).build(); // 表达式调度构建器
CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCronExpression());
cronScheduleBuilder = handleCronScheduleMisfirePolicy(job, cronScheduleBuilder); // 按新的cronExpression表达式构建一个新的trigger
CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(getTriggerKey(job.getJobId()))
.withSchedule(cronScheduleBuilder).build(); // 放入参数,运行时的方法可以获取
jobDetail.getJobDataMap().put(ScheduleConstants.TASK_PROPERTIES, job); scheduler.scheduleJob(jobDetail, trigger); // 暂停任务
if (job.getStatus().equals(ScheduleConstants.Status.PAUSE.getValue()))
{
pauseJob(scheduler, job.getJobId());
}
}
catch (SchedulerException e)
{
log.error("createScheduleJob 异常:", e);
}
catch (TaskException e)
{
log.error("createScheduleJob 异常:", e);
}
} /**
* 更新定时任务
*/
public static void updateScheduleJob(Scheduler scheduler, SysJob job)
{
try
{
TriggerKey triggerKey = getTriggerKey(job.getJobId()); // 表达式调度构建器
CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCronExpression());
cronScheduleBuilder = handleCronScheduleMisfirePolicy(job, cronScheduleBuilder); CronTrigger trigger = getCronTrigger(scheduler, job.getJobId()); // 按新的cronExpression表达式重新构建trigger
trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(cronScheduleBuilder).build(); // 参数
trigger.getJobDataMap().put(ScheduleConstants.TASK_PROPERTIES, job); scheduler.rescheduleJob(triggerKey, trigger); // 暂停任务
if (job.getStatus().equals(ScheduleConstants.Status.PAUSE.getValue()))
{
pauseJob(scheduler, job.getJobId());
} }
catch (SchedulerException e)
{
log.error("SchedulerException 异常:", e);
}
catch (TaskException e)
{
log.error("SchedulerException 异常:", e);
}
} /**
* 立即执行任务
*/
public static int run(Scheduler scheduler, SysJob job)
{
int rows = 0;
try
{
// 参数
JobDataMap dataMap = new JobDataMap();
dataMap.put(ScheduleConstants.TASK_PROPERTIES, job); scheduler.triggerJob(getJobKey(job.getJobId()), dataMap);
rows = 1;
}
catch (SchedulerException e)
{
log.error("run 异常:", e);
}
return rows;
} /**
* 暂停任务
*/
public static void pauseJob(Scheduler scheduler, Long jobId)
{
try
{
scheduler.pauseJob(getJobKey(jobId));
}
catch (SchedulerException e)
{
log.error("pauseJob 异常:", e);
}
} /**
* 恢复任务
*/
public static void resumeJob(Scheduler scheduler, Long jobId)
{
try
{
scheduler.resumeJob(getJobKey(jobId));
}
catch (SchedulerException e)
{
log.error("resumeJob 异常:", e);
}
} /**
* 删除定时任务
*/
public static void deleteScheduleJob(Scheduler scheduler, Long jobId)
{
try
{
scheduler.deleteJob(getJobKey(jobId));
}
catch (SchedulerException e)
{
log.error("deleteScheduleJob 异常:", e);
}
} public static CronScheduleBuilder handleCronScheduleMisfirePolicy(SysJob job, CronScheduleBuilder cb)
throws TaskException
{
switch (job.getMisfirePolicy())
{
case ScheduleConstants.MISFIRE_DEFAULT:
return cb;
case ScheduleConstants.MISFIRE_IGNORE_MISFIRES:
return cb.withMisfireHandlingInstructionIgnoreMisfires();
case ScheduleConstants.MISFIRE_FIRE_AND_PROCEED:
return cb.withMisfireHandlingInstructionFireAndProceed();
case ScheduleConstants.MISFIRE_DO_NOTHING:
return cb.withMisfireHandlingInstructionDoNothing();
default:
throw new TaskException("The task misfire policy '" + job.getMisfirePolicy() + "' cannot be used in cron schedule tasks", Code.CONFIG_ERROR);
}
}
}

quartz监控日志(四)自定义QuartzJobBean来实现监控的更多相关文章

  1. Security基础(六):部署Zabbix监控平台、配置及使用Zabbix监控系统、自定义Zabbix监控项目、实现Zabbix报警功能

    一.部署Zabbix监控平台 目标: 本案例要求部署一台Zabbix监控服务器,一台被监控主机,为进一步执行具体的监控任务做准备: 在监控服务器上安装LAMP环境    修改PHP配置文件,满足Zab ...

  2. 【运维监控】四款云服务监控工具介绍:Nagios 、 ganglia、zabbix、onealert

    在我们日常的工作中,有时候需要监控和管理平台的运行状况,而服务运行是否存在异常,是否有软硬件bug等,均需要第一时间知道.对服务状态了如指掌,是一个很重要的事情.那么这个如何做到呢,我们之前在进行私有 ...

  3. zabbix之 自定义(指定特定磁盘)监控io

    引言 zabbix自带的模板,并且完成了我们的一些比较常用的监控,现在我们如果想要监控我们磁盘的IO,这时候zabbix并没有给我们提供这么一个模板,所以我们需要自己来创建一个模板来完成磁盘IO的监控 ...

  4. zabbix3.4.7主动模式监控日志(多关键字)

    日志监控原理 1.Zabbix Server和Zabbix Agent会追踪日志文件的大小和最后修改时间,并且分别记录在字节计数器和最新的时间计数器中. 2.Agent会从上次读取日志的地方开始读取日 ...

  5. 【教程】Tomcat 的catalina.out 日志按照自定义日期格式进行切割

    本文简单介绍在使用cronolog对tomcat的日志进行自定义日期格式的切割,方便日志的整理和遇到问题日志的排查! 安装cronolog 安装cronolog的方法网上有很多,这里也简单的介绍一下. ...

  6. 基于sentry的前端错误监控日志系统(部署sentry服务器/前端项目部署)-让前端最快的定位到生产问题

    背景 在这越来越发达的网络时代,web应用也是越来越复杂,尤其是前端的开发,也是越来越受重视. 所以在我们前端开发完成后,会有一些列的web应用的上线验证,如自测.QA测试.code review 等 ...

  7. 四十八.监控概述 、 Zabbix基础 、 Zabbix监控服务

     1.常用系统监控命令 查看内存信息 查看交换分区信息 查看磁盘信息 查看CPU信息 查看网卡信息 查看端口信息 查看网络连接信息   一般企业做监控的目的:实时报告系统状态,提前发现系统的问题. 监 ...

  8. 学习总结 之 WebApi服务监控 log4net记录监控日志

    在请求WebApi 的时候,我们更想知道在请求数据的时候,调用了哪个接口传了什么参数过来,调用这个Action花了多少时间,有没有人恶意请求.我们可以通过记录日志,对Action进行优化,可以通过日志 ...

  9. log4net 记录MVC监控日志

    由于MVC自身的特点,可以让我们记录每一个Controller下Action的执行时间以及View视图渲染完成的时间,本文采用log4net记录MVC每个Action的执行时间和View视图渲染完成时 ...

  10. 探索Windows Azure 监控和自动伸缩系列3 - 启用Azure监控扩展收集自定义监控数据

    上一篇我们介绍了获取Azure的监控指标和监控数据: http://www.cnblogs.com/teld/p/5113376.html 本篇我们继续:监控虚拟机的自定义性能计数器. 随着我们应用规 ...

随机推荐

  1. 我又学会了使用Range实现网络文件下载的断点续传

    目录 前言 1.Range请求头 1.1.概述 1.2.使用限制 1.3.范围请求 1.4.预防资源变更 2.断点续传下载实现 2.1.流程设计 2.2.代码实现 2.3.运行结果 3.RandomA ...

  2. Linux 内核:设备驱动模型(3)class与device

    Linux 内核:设备驱动模型(3)class与device 背景 前面我们知道了设备如何通过总线与驱动匹配,也了解了设备插拔时与用户空间是如何通过uevent基于环境变量进行交互的. 前面看过了设备 ...

  3. 处理 3d 视频的简单理论基础

    背景 公司产品需要满足一些带有3d功能的应用场景,需要需要懂得如何处理3d信号.之前在调试以前产品的时候,发现处理3d信号的时候,是由2个画面叠加起来的. 导言 3D视频(或3D信号)为什么是两个画面 ...

  4. 『vulnhub系列』Hack Me Please-1

    『vulnhub系列』Hack Me Please-1 下载地址: https://www.vulnhub.com/entry/hack-me-please-1,731/ 信息搜集: 使用nmap进行 ...

  5. 升级到 MySQL 8.4,MySQL 启动报错:io_setup() failed with EAGAIN

    问题 最近碰到一个 case,一台主机上,部署了多个实例.之前使用的是 MySQL 8.0,启动时没有任何问题.但升级到 MySQL 8.4 后,部分实例在启动时出现了以下错误. [Warning]  ...

  6. 常用 Java 组件和框架分类

    WEB 容器 Tomcat https://tomcat.apache.org/ Jetty https://www.jetty.com/ JBoss https://www.jboss.org/ R ...

  7. 记一次Redis实施故障

    服务在测试环境运行没问题,部署到生产环境,连redis时报下面的错误: [2022-11-04 00:00:09][org.springframework.scheduling.support.Tas ...

  8. Pandas库学习笔记(5)---Pandas Panel

    Pandas Panel Pandas Panel基本操作 Panel数据3D容器. 术语 Panel data 源自计量经济学,名称来之于pandas − pan(el)-da(ta)-s. 3个轴 ...

  9. Vue 中引用第三方js总结

    vue中引用第三方js总结 By:授客 QQ:1033553122 实践环境 win10 Vue 2.9.6 本文以引用jsmind为例,讲解怎么在vue中引用第三方js类库 基础示例 1.把下载好的 ...

  10. Codeforces Round 953 (Div. 2)

    Codeforces Round 953 (Div. 2) 闲来无事水题解. A . B . C 显然 \(k\) 是偶数.考虑 \(k\) 的上界,\(p_{1}=n,p_{n}=1\),产生 \( ...