`
征途2010
  • 浏览: 246567 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

quartz监控日志(一)

阅读更多

最近几个月,现网总是出现定时器不执行的情况,或者定时器卡死的情况,而又不方便排查,只能依靠quartz的debug日志以及错误日志来监控定时器的执行情况,并且随着我们系统中job越来越多,而使得job问题越来越难以跟踪,所以我们才需要一个能过对定时器进行监控的功能,并能实现线程阻塞告警,以及杀死阻塞线程的功能。

监控job有几种方案:

方案一:通过jmx远程或者直接在应用内部定时获取quartz执行信息,可以新增、修改job、job触发器以及执行情况,但是无法对以前执行的job进行跟踪。

方案二:在job的实现类中记录日志,这个方案太麻烦,因为系统目前有很多job实现类,不可能每个都去添加日志。

方案三:代理job执行类,在初始化时使用代理job执行器。

 

最后我选择了方案三。

先让我们来分析下源码,目前只针对quartz1.6.0:

首先查看JobRunShell类,这个是定时器的执行类实现了Runnable接口,它有两个空方法如下:

public class JobRunShell implements Runnable {
   public void run() {
      //省略若干代码
             try {
                begin();
            } catch (SchedulerException se) {
                qs.notifySchedulerListenersError("Error executing Job ("
                        + jec.getJobDetail().getFullName()
                        + ": couldn't begin execution.", se);
                break;
            }
      //省略若干代码
           try {
                complete(true);
            } catch (SchedulerException se) {
                qs.notifySchedulerListenersError("Error executing Job ("
                        + jec.getJobDetail().getFullName()
                        + ": couldn't finalize execution.", se);
                continue;
            }
       }
  protected void begin() throws SchedulerException {
    }

    protected void complete(boolean successfulExecution)
        throws SchedulerException {
    }

}

 很明显,这里预留了两个方法来监控job的执行情况。

所以我们创建了一个其子类来代理它,在开始时记录日志,结束时更新日志,

 

public class MonitorJobRunShell extends JobRunShell {
     
    /**    
     * 创建一个新的实例 JobRunShellImpl.  
     * @param jobRunShellFactory
     * @param scheduler
     * @param schdCtxt    
     */
    public MonitorJobRunShell(JobRunShellFactory jobRunShellFactory, Scheduler scheduler, SchedulingContext schdCtxt) {
        super(jobRunShellFactory, scheduler, schdCtxt);
    }

    @Override
    protected void begin() throws SchedulerException {
        super.begin();
        try {
            JobDetail jobDetail = jec.getJobDetail();
            quartzLog=getService().insert(jobDetail.getName());
        } catch (Exception e) {
            logger.error("记录job开始时间异常",e);
        }catch (Throwable e) {
            logger.error("记录job开始时间出错",e);
        }
        
    }

    @Override
    protected void complete(boolean successfulExecution) throws SchedulerException {
        super.complete(successfulExecution);
        try {
            quartzLog.setExeTime(jec.getJobRunTime());
            getService().update(quartzLog);
        } catch (Exception e) {
            logger.error("记录job结束时间异常",e);
        }catch (Throwable e) {
            logger.error("记录job结束时间出错",e);
        }
    }
}

 创建了该类,必须要让quartz使用我们创建的代理类,这里quartz使用了简单工厂模式,如下

public interface JobRunShellFactory {
  /**
     * <p>
     * Called by the <code>{@link org.quartz.core.QuartzSchedulerThread}</code>
     * to obtain instances of <code>{@link JobRunShell}</code>.
     * </p>
     */
    JobRunShell borrowJobRunShell() throws SchedulerException;

}

 我们只需要实现该接口,代理原有的std工厂类:

public class StdJobRunShellFactoryProxy implements JobRunShellFactory{
  

    /**
     * <p>
     * Called by the <class>{@link org.quartz.core.QuartzSchedulerThread}
     * </code> to obtain instances of <code>
     * {@link org.quartz.core.JobRunShell}</code>.
     * </p>
     */
    public JobRunShell borrowJobRunShell() throws SchedulerException {
        return new MonitorJobRunShell(this, scheduler, schedCtxt);
    }

    /**
     * <p>
     * Called by the <class>{@link org.quartz.core.QuartzSchedulerThread}
     * </code> to return instances of <code>
     * {@link org.quartz.core.JobRunShell}</code>.
     * </p>
     */
    public void returnJobRunShell(JobRunShell jobRunShell) {
        jobRunShell.passivate();
    }
}

 

进行到这里,需要使用到我们的工厂代理类,这时候则需要代理入口,即StdSchedulerFactory,

public class StdSchedulerFactoryProxy extends StdSchedulerFactory {

    
    /**
     * 初始化Scheduler
     * 同时,替换JobRunShellFactory,并启动清理job日志线程
     * @see org.quartz.impl.StdSchedulerFactory#instantiate(org.quartz.core.QuartzSchedulerResources, org.quartz.core.QuartzScheduler)
     */
    protected Scheduler instantiate(QuartzSchedulerResources rsrcs, QuartzScheduler qs) {
        SchedulingContext schedCtxt = new SchedulingContext();
        schedCtxt.setInstanceId(rsrcs.getInstanceId());
        Scheduler scheduler = new StdScheduler(qs, schedCtxt);
        try {
            JobRunShellFactory jobFactory=new StdJobRunShellFactoryProxy();
            jobFactory.initialize(scheduler, schedCtxt);
            rsrcs.setJobRunShellFactory(jobFactory);
        } catch (SchedulerConfigException e) {
            logger.error("初始化MonitorStdJobRunShellFactory出错",e);
        }
        return scheduler;
    }
}

 

最后在初始化Scheduler时使用我们代理的Scheduler工厂类就行,实例如下:

StdSchedulerFactory factory = new StdSchedulerFactoryProxy();

这里我们就实现了自己的quartz监控程序,日志记录方式可以自己扩展。这样可以有效方便的监控job的执行情况,日志中可以记录job的执行时长、线程id等,可以配置阈值如果超时可以在界面上kill该线程。

 

 

 

1
4
分享到:
评论

相关推荐

    Quartz任务监控管理

    4. **监控和管理**:此项目特别强调“任务监控管理”,因此会包含监控任务状态、查看日志、报警机制等功能。开发者可能通过自定义Listener或者使用Quartz提供的内置监听器来监控Job的执行情况。 5. **异常处理**:...

    quartz 定时任务调度

    Quartz是一个开源的作业调度库,它允许开发人员将作业和触发器定义并排程到一个可持久化的存储中。这些作业可以在预定的时间或基于某些触发条件执行。Quartz具有高度的可扩展性,支持多线程和分布式环境,适用于...

    对Quartz的简单封装

    5. **日志集成**:集成日志框架,记录任务的执行情况,便于调试和监控。 6. **任务监控**:可能提供了一个简单的Web界面或者API接口,用于查看任务状态、触发器信息以及执行历史,帮助运维人员实时了解任务运行状况...

    quartz一个定时触发实例

    6. **监听器(Listeners)**:Quartz提供了多种监听器,如JobListener、TriggerListener,可以监听作业和触发器的生命周期事件,为日志记录、监控提供便利。 7. **集群支持**:Quartz可以部署在集群环境中,多个...

    Quartz所需jar包

    2. `slf4j-api.jar`:Simple Logging Facade for Java,Quartz依赖于它来进行日志记录,你可以根据自己的日志系统选择对应的实现,比如`logback-classic.jar`或`log4j.jar`。 3. `common-jdbc.jar`(可能包含):...

    QuartzDemo

    `CrystalQuartz.OwinConsole`可能是一个用于在OWIN服务器环境中运行和监控Quartz作业的模块。Owin是微软的一个轻量级Web服务器接口,而CrystalQuartz是一个强大的Quartz.NET管理界面,它允许开发者通过用户友好的...

    使用quartz需要的jar包

    - 调试与监控:利用日志系统跟踪Quartz的运行状态,可以使用Quartz提供的监控工具(如` quartz-admin.jar`)进行远程监控和管理。 综上所述,使用Quartz时,正确引入和配置相关的jar包是确保程序正常运行的关键。...

    QUARTZ项目实练

    - **监控与日志**:可以集成监控工具,如Quartz Admin,以便实时查看任务状态,同时确保有良好的日志记录系统,便于问题排查。 在"quartz-mybatis"压缩包中,应包含QUARTZ的配置文件、Mybatis的Mapper接口和XML...

    Springboot2+quartz可视化+logback

    同时,为了实现Quartz的可视化,还需要引入一个Web UI组件,如JobAdmin或QuartzSchedulerWebApp,这些UI工具可以帮助我们监控和管理Quartz作业。 【Quartz的Web UI】 描述中提到的"web ui"是指为Quartz提供了一个...

    quartz动态任务管理

    5. **监听器(Listener)**:可以监听作业和触发器的生命周期事件,提供日志、监控等功能。 6. **持久化**:Quartz支持数据库持久化,即使在服务器重启后也能恢复之前的状态,保证任务的连续性。 7. **API和工具类...

    springboot整合quartz完整项目

    可以利用Quartz提供的管理界面(如`QuartzAdmin`)或者通过编写API接口,来实时监控和管理定时任务的状态,查看任务执行日志,以及进行手动触发等操作。 综上所述,SpringBoot整合Quartz的完整项目可以帮助开发者...

    C#实现quartz.net3.0.7和topshelf4.2.1创建windows服务

    在本文中,我们将深入探讨如何使用C#与quartz.net 3.0.7和topshelf 4.2.1库来创建一个Windows服务。quartz.net是一个开源的作业调度框架,而topshelf则是一个轻量级的库,用于简化在.NET环境中创建Windows服务的过程...

    Quartz多线程示例.rar

    同时,日志记录也非常重要,示例可能利用了Quartz的日志功能,以便追踪和调试任务执行过程中的问题。 总之,"Quartz多线程示例"是一个很好的学习资源,它教你如何利用Quartz的多线程能力来并发执行任务,以及如何...

    quartz 项目学习源码

    Quartz 是一个开源的作业调度框架,用于在 Java 应用程序中安排任务。它提供了丰富的 API 和功能,使得开发者可以灵活地定义、调度和管理各种类型的任务。在这个"quartz 项目学习源码"中,你可以深入理解 Quartz 的...

    定时任务设置及实现quartz

    Quartz提供了多种错误处理策略,如重试、跳过、记录日志等,可依据业务需求进行设置。 9. 性能优化: 调整Quartz配置以优化性能,如减少不必要的内存占用、调整线程池大小等。同时,合理设计CronTrigger或...

    Quartz.NET

    Quartz.NET是一个强大的开源作业调度框架,用于在.NET环境中创建和执行计划任务。它提供了高度灵活的调度功能,使得开发者可以轻松地安排程序在特定时间执行。Quartz.NET基于Java版的Quartz项目,但完全用C#重写,...

    quartz+spring分布式集群调度

    3. **监控和管理**: 实现对Quartz集群的监控,如任务状态、运行时性能等,以便及时发现和解决问题。 总结,Quartz+Spring的分布式集群调度方案能够帮助开发者构建稳定且可扩展的定时任务系统。通过合理配置和实践,...

    quartz2.2.1帮助手册

    4. **插件架构**:Quartz 提供了插件化的设计,允许添加自定义的插件来扩展其功能,如邮件通知、日志记录等。 5. **作业商店**:Quartz 的作业商店(Job Store)提供了多种存储策略,包括内存、JDBC、RAM等,开发者...

    servlet整合quartz2所需quartz2包

    6. **监控和管理**:可以通过Quartz提供的API或Web界面来监控和管理任务,例如暂停、恢复、删除任务,或者查看任务状态。 7. **处理Servlet请求**:在Servlet中,可以创建一个端点来触发任务的立即执行,或者更新...

    Quartz 2.1.3

    Quartz 2.1.3 是一个开源的作业调度框架,专为Java应用程序设计,用于在特定时间执行任务。这个框架允许开发者精确地控制任务的执行时间,从而实现自动化的工作流程。Quartz 提供了丰富的 API 和调度功能,使得...

Global site tag (gtag.js) - Google Analytics