飞翔飞翔
主页
  • 计算机基础

    • TCP协议
  • 数据库

    • SQL教程
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON教程
  • 工具

    • Markdown指南
  • Git

    • GitFlow
  • Quartz

    • Quartz教程
  • Java

    • Java设计模式
  • 缓存

    • Redis教程
联系
阿里云
主页
  • 计算机基础

    • TCP协议
  • 数据库

    • SQL教程
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON教程
  • 工具

    • Markdown指南
  • Git

    • GitFlow
  • Quartz

    • Quartz教程
  • Java

    • Java设计模式
  • 缓存

    • Redis教程
联系
阿里云
  • 前言

    • 1.起步
  • 第1章 快速入门指南

    • 1.下载和安装
    • 2.配置
    • 3.运行一个简单的应用
  • 第2章 Quartz教程

    • 1.使用Quartz
    • 2.Quartz API、作业和触发器
    • 3.更多关于作业和作业详细信息
    • 4.更多关于触发器
    • 5.简单触发器
    • 6.Cron触发器
    • 7.触发器监听器和作业监听器
    • 8.调度程序监听器
    • 9.作业存储JobStore
    • 10.配置、资源使用和调度器工厂
    • 11.高级(企业)功能
    • 12.Quartz的其他特征
    • 13.专题之Corn触发器教程
  • 第3章 15个官网示例

    • 概览
    • 1.示例1 - 你的第一个Quartz程序
    • 2.示例2 - 简单触发器
    • 3.示例3 - Cron触发器
    • 4.示例4 - 作业状态和参数
    • 5.示例5 - 处理作业失误
    • 6.示例6 - 处理作业异常
    • 7.示例7 - 中断作业
    • 8.示例8 - 日历带来的乐趣
    • 9.示例9 - 作业监听器
    • 10.示例10 - 使用Quartz插件
    • 11.示例11 - 高负载下的Quartz
    • 12.示例12 - 使用RMI的远程作业调度
    • 13.示例13 - 集群化的Quartz
    • 14.示例14 - 触发器优先级
    • 15.示例15 - TC集群化的Quartz

示例12 - 使用RMI的远程作业调度

说明

此示例演示使用远程方法调用,Quartz调度器可以由客户端远程调度。

SimpleJob.java源码

package org.quartz.examples.example12;

import java.util.Date;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.JobKey;

/**
 * Job的一个缺陷实现,用于单元测试
 * 作者:James House
 */
public class SimpleJob implements Job {

    public static final String MESSAGE = "msg";

    private static Logger _log = LoggerFactory.getLogger(SimpleJob.class);

    /**
     * Quartz需要一个公共的空参构造函数,以便调度器可以在需要时实例化类
     */
    public SimpleJob() {
    }

    /**
     * 当与此作业相关联的触发器触发时,由调度器调用此方法
     * Throws:作业执行异常(JobExecutionException)-当执行作业时产生异常
     */
    public void execute(JobExecutionContext context)
        throws JobExecutionException {

        //此作业简单地输出它的名称及运行时间
        JobKey jobKey = context.getJobDetail().getKey();

        String message = (String) context.getJobDetail().getJobDataMap().get(MESSAGE);

        _log.info("SimpleJob: " + jobKey + " executing at " + new Date());
        _log.info("SimpleJob: msg: " + message);
    }

    

}

RemoteServerExample.java源码

package org.quartz.examples.example12;

import org.quartz.Scheduler;
import org.quartz.SchedulerFactory;
import org.quartz.SchedulerMetaData;
import org.quartz.impl.StdSchedulerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 作者:Bill Kratzer
 */
public class RemoteServerExample {

  /**
   * 此示例将产生大量要执行的作业
   * 作者:James House, Bill Kratzer
   */
  public void run() throws Exception {
    Logger log = LoggerFactory.getLogger(RemoteServerExample.class);

    //首先,我们必须获得对调度器的引用
    SchedulerFactory sf = new StdSchedulerFactory();
    Scheduler sched = sf.getScheduler();

    log.info("------- Initialization Complete -----------");

    log.info("------- (Not Scheduling any Jobs - relying on a remote client to schedule jobs --");

    log.info("------- Starting Scheduler ----------------");

    //开启调度器
    sched.start();

    log.info("------- Started Scheduler -----------------");

    log.info("------- Waiting ten minutes... ------------");

    //等待5分钟让我们的作业有机会执行
    try {
      Thread.sleep(600L * 1000L);
    } catch (Exception e) {
      //
    }

    //关闭调度器
    log.info("------- Shutting Down ---------------------");
    sched.shutdown(true);
    log.info("------- Shutdown Complete -----------------");

    SchedulerMetaData metaData = sched.getMetaData();
    log.info("Executed " + metaData.getNumberOfJobsExecuted() + " jobs.");
  }

  public static void main(String[] args) throws Exception {

    RemoteServerExample example = new RemoteServerExample();
    example.run();
  }

}

RemoteClientExample.java源码

package org.quartz.examples.example12;

import static org.quartz.CronScheduleBuilder.cronSchedule;
import static org.quartz.JobBuilder.newJob;
import static org.quartz.TriggerBuilder.newTrigger;
import org.quartz.JobDataMap;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerFactory;
import org.quartz.Trigger;
import org.quartz.impl.StdSchedulerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 此示例是一个客户端程序,它将远程与调度器进行通信以调度作业。在本例中,我们需要使用JDBC作业存储。
 * 客户端将远程连接到JDBC作业存储以调度作业。
 * 作者:James House, Bill Kratzer
 */
public class RemoteClientExample {

    public void run() throws Exception {

        Logger log = LoggerFactory.getLogger(RemoteClientExample.class);

        //首先,我们必须获得对调度器的引用
        SchedulerFactory sf = new StdSchedulerFactory();
        Scheduler sched = sf.getScheduler();

        //定义作业并要求其执行
        JobDetail job = newJob(SimpleJob.class)
            .withIdentity("remotelyAddedJob", "default")
            .build();
        
        JobDataMap map = job.getJobDataMap();
        map.put("msg", "Your remotely added job has executed!");
        
        Trigger trigger = newTrigger()
            .withIdentity("remotelyAddedTrigger", "default")
            .forJob(job.getKey())
            .withSchedule(cronSchedule("/5 * * ? * *"))
            .build();

        //安排作业
        sched.scheduleJob(job, trigger);

        log.info("Remote job scheduled.");
    }

    public static void main(String[] args) throws Exception {

        RemoteClientExample example = new RemoteClientExample();
        example.run();
    }

}

配置文件

本示例需要 server.properties 和 client.properties 配置文件,它们位于 examples/example12 目录中。

server.properties

服务端的配置文件,启用RMI导出:

#============================================================================
# 配置主调度器属性
#============================================================================

org.quartz.scheduler.instanceName: Sched1
org.quartz.scheduler.rmi.export: true
org.quartz.scheduler.rmi.registryHost: localhost
org.quartz.scheduler.rmi.registryPort: 1099
org.quartz.scheduler.rmi.createRegistry: true

#============================================================================
# 配置线程池
#============================================================================

org.quartz.threadPool.class: org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount: 10
org.quartz.threadPool.threadPriority: 5

#============================================================================
# 配置JobStore
#============================================================================

org.quartz.jobStore.misfireThreshold: 60000

org.quartz.jobStore.class: org.quartz.simpl.RAMJobStore

关键配置说明:

  • rmi.export: true:将调度器通过RMI导出,允许远程客户端连接
  • rmi.registryHost:RMI注册表的主机地址
  • rmi.registryPort: 1099:RMI注册表的端口号
  • rmi.createRegistry: true:自动创建RMI注册表

client.properties

客户端的配置文件,通过RMI代理连接到远程调度器:

# Properties file for use by StdSchedulerFactory
# to create a Quartz Scheduler Instance.

# 配置主调度器属性

org.quartz.scheduler.instanceName: Sched1
org.quartz.scheduler.logger: schedLogger
org.quartz.scheduler.rmi.proxy: true
org.quartz.scheduler.rmi.registryHost: localhost
org.quartz.scheduler.rmi.registryPort: 1099

关键配置说明:

  • rmi.proxy: true:以代理模式运行,连接到远程调度器而非创建本地实例
  • rmi.registryHost:远程RMI注册表的主机地址(如果客户端和服务端在不同机器上,需修改为服务端的IP地址)
  • rmi.registryPort: 1099:远程RMI注册表的端口号,需与服务端一致

注意

如果客户端和服务端运行在不同机器上,需要修改 client.properties 中的 registryHost 为服务端的实际IP地址。

运行示例

启动步骤

  1. 启动服务端:

    • server.sh——UNIX/Linux shell脚本
    • server.bat——Windows批处理文件
  2. 启动客户端(服务端启动后):

    • client.sh——UNIX/Linux shell脚本
    • client.bat——Windows批处理文件

提示

本示例最好在不同计算机上分别运行客户端和服务端。如果在同一台机器上运行,确保先启动服务端,再启动客户端。

控制台输出(RemoteServerExample)

[main] INFO org.quartz.impl.StdSchedulerFactory - Using default implementation for ThreadExecutor
[main] INFO org.quartz.simpl.SimpleThreadPool - Job execution threads will use class loader of thread: main
[main] INFO org.quartz.core.SchedulerSignalerImpl - Initialized Scheduler Signaller of type: class org.quartz.core.SchedulerSignalerImpl
[main] INFO org.quartz.core.QuartzScheduler - Quartz Scheduler v.2.3.0 created.
[main] INFO org.quartz.simpl.RAMJobStore - RAMJobStore initialized.
[main] INFO org.quartz.core.QuartzScheduler - Scheduler meta-data: Quartz Scheduler (v2.3.0) 'DefaultQuartzScheduler' with instanceId 'NON_CLUSTERED'
  Scheduler class: 'org.quartz.core.QuartzScheduler' - running locally.
  NOT STARTED.
  Currently in standby mode.
  Number of jobs executed: 0
  Using thread pool 'org.quartz.simpl.SimpleThreadPool' - with 10 threads.
  Using job-store 'org.quartz.simpl.RAMJobStore' - which does not support persistence. and is not clustered.

[main] INFO org.quartz.impl.StdSchedulerFactory - Quartz scheduler 'DefaultQuartzScheduler' initialized from default resource file in Quartz package: 'quartz.properties'
[main] INFO org.quartz.impl.StdSchedulerFactory - Quartz scheduler version: 2.3.0
[main] INFO org.quartz.examples.example12.RemoteServerExample - ------- Initialization Complete -----------
[main] INFO org.quartz.examples.example12.RemoteServerExample - ------- (Not Scheduling any Jobs - relying on a remote client to schedule jobs --
[main] INFO org.quartz.examples.example12.RemoteServerExample - ------- Starting Scheduler ----------------
[main] INFO org.quartz.core.QuartzScheduler - Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED started.
[main] INFO org.quartz.examples.example12.RemoteServerExample - ------- Started Scheduler -----------------
[main] INFO org.quartz.examples.example12.RemoteServerExample - ------- Waiting ten minutes... ------------

控制台输出(RemoteClientExample)

[main] INFO org.quartz.impl.StdSchedulerFactory - Using default implementation for ThreadExecutor
[main] INFO org.quartz.simpl.SimpleThreadPool - Job execution threads will use class loader of thread: main
[main] INFO org.quartz.core.SchedulerSignalerImpl - Initialized Scheduler Signaller of type: class org.quartz.core.SchedulerSignalerImpl
[main] INFO org.quartz.core.QuartzScheduler - Quartz Scheduler v.2.3.0 created.
[main] INFO org.quartz.simpl.RAMJobStore - RAMJobStore initialized.
[main] INFO org.quartz.core.QuartzScheduler - Scheduler meta-data: Quartz Scheduler (v2.3.0) 'DefaultQuartzScheduler' with instanceId 'NON_CLUSTERED'
  Scheduler class: 'org.quartz.core.QuartzScheduler' - running locally.
  NOT STARTED.
  Currently in standby mode.
  Number of jobs executed: 0
  Using thread pool 'org.quartz.simpl.SimpleThreadPool' - with 10 threads.
  Using job-store 'org.quartz.simpl.RAMJobStore' - which does not support persistence. and is not clustered.

[main] INFO org.quartz.impl.StdSchedulerFactory - Quartz scheduler 'DefaultQuartzScheduler' initialized from default resource file in Quartz package: 'quartz.properties'
[main] INFO org.quartz.impl.StdSchedulerFactory - Quartz scheduler version: 2.3.0
[main] INFO org.quartz.examples.example12.RemoteClientExample - Remote job scheduled.
上一页
11.示例11 - 高负载下的Quartz
下一页
13.示例13 - 集群化的Quartz