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. 无法启动 IIS Express Web 服务器.....另一个程序正在使用此文件,进程无法访问。 问题解决

    一般是由于端口被占用导致的,但是这个端口你在命令行netstat -a里 排除 如果发现被占用,那么就kill进程就可以了 如果没有发现被占用,依然无法启动,可以尝试以下方法 解决方案1: 修改iis ...

  2. 你不知道的 CSS 之包含块

    你不知道的 CSS 之包含块 一说到 CSS 盒模型,这是很多小伙伴耳熟能详的知识,甚至有的小伙伴还能说出 border-box 和 content-box 这两种盒模型的区别. 但是一说到 CSS ...

  3. java并发的发布和订阅测试

    现在编码的时候,为了处理消息,大家动不动就上个重器,例如MQ之类的.但很多时候,并不是那么有必要,因为数据量和并发其实远远不够. 可以替代的方案非常多,其中一个是java.util.concurren ...

  4. 一些自托管(self hosted)服务的使用笔记

    opengrok oracle的opengrok是一个项目代码查找工具,自建索引,类似工具有source insight 官方已经提供好了docker镜像,傻瓜式安装.不过增加新的项目源码时需要手动更 ...

  5. 高通与At指令:AtCop解析

    背景 在某个新基线上移植AT指令,发现有问题,因此收集了这个系列的 文章 作为 这方面的知识补充. 原文作者:laozhuxinlu,本文有删改. 另外,还参考了:https://www.cnblog ...

  6. 通过 hexo 生成静态博客

    通过 hexo 生成静态博客 背景 在对比了很多博客网站以后,我决定开始慢慢迁移我的文章,以后有时间的话还会搭建自己的网站,目前主流的静态博客生成器有三个: jekyll, hexo, hugo. 静 ...

  7. 基于MCU的SD卡fat文件系统读写移植

    背景 https://blog.csdn.net/huang20083200056/article/details/78508490 SD卡(Secure Digital Memory Card)具有 ...

  8. 基于 TI Sitara系列 AM64x核心板——程序自启动说明

    前 言 本文主要介绍AM64x的Cortex-A53.Cortex-M4F和Cortex-R5F核心程序自启动使用说明.默认使用AM6442进行测试演示,AM6412测试步骤与之类似. 本说明文档适用 ...

  9. Java Objects工具类重点方法使用

    Objects工具类 jdk 1.7引进的工具类,都是静态调用的方法,jdk 1.8新增了部分方法 重点方法 equals 用于字符串和包装对象的比较,先比较内存地址,再比较值 deepEquals ...

  10. 解决方案 | 笔记本电脑能连上WIFI,但是无Internet显示地球图标,怎么回事?(win10)

    一.背景 任务栏托盘区显示地球图标,但是实际上可以上网. 疑难诊断一般是这种情况: 二.可能的有效解决方案 0 方案0:使用360断网急救箱傻瓜式修复 个人制作 | 360断网急救箱新版-2.0版单文 ...