`
emptyhan
  • 浏览: 29832 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

spring+quartz集群

    博客分类:
  • J2EE
阅读更多
转载自 http://www.iteye.com/topic/486055 和 http://julylin.iteye.com/blog/849100

概述

虽然单个Quartz实例能给予你很好的Job调度能力,但它不能满足典型的企业需求,如可伸缩性、高可靠性满足。假如你需要故障转移的能力并能运行日益增多的 Job,Quartz集群势必成为你应用的一部分了。使用 Quartz 的集群能力可以更好的支持你的业务需求,并且即使是其中一台机器在最糟的时间崩溃了也能确保所有的 Job 得到执行。

Quartz 中集群如何工作

一个 Quartz 集群中的每个节点是一个独立的 Quartz 应用,它又管理着其他的节点。意思是你必须对每个节点分别启动或停止。不像许多应用服务器的集群,独立的 Quartz 节点并不与另一其的节点或是管理节点通信。Quartz 应用是通过数据库表来感知到另一应用的。

图:表示了每个节点直接与数据库通信,若离开数据库将对其他节点一无所知

创建Quartz数据库表

因为Quartz 集群依赖于数据库,所以必须首先创建Quartz数据库表。Quartz 包括了所有被支持的数据库平台的 SQL 脚本。在 <quartz_home>/docs/dbTables 目录下找到那些 SQL 脚本,这里的 <quartz_home> 是解压 Quartz 分发包后的目录。
这里采用的Quartz 2.0.2版本,总共11张表,不同版本,表个数可能不同。数据库为mysql,用tables_mysql.sql创建数据库表。

介绍下主要的几张表:
       表qrtz_job_details: 保存job详细信息,该表需要用户根据实际情况初始化
       job_name:集群中job的名字,该名字用户自己可以随意定制,无强行要求
       job_group:集群中job的所属组的名字,该名字用户自己随意定制,无强行要求
       job_class_name:集群中个note job实现类的完全包名,quartz就是根据这个路径到classpath找到该job类
       is_durable:是否持久化,把该属性设置为1,quartz会把job持久化到数据库中
       job_data:一个blob字段,存放持久化job对象

       表qrtz_triggers: 保存trigger信息
       trigger_name: trigger的名字,该名字用户自己可以随意定制,无强行要求
       trigger_group:trigger所属组的名字,该名字用户自己随意定制,无强行要求
       job_name: qrtz_job_details表job_name的外键
       job_group: qrtz_job_details表job_group的外键
       trigger_state:当前trigger状态,设置为ACQUIRED,如果设置为WAITING,则job不会触发
       trigger_cron:触发器类型,使用cron表达式

       表qrtz_cron_triggers:存储cron表达式表
       trigger_name: qrtz_triggers表trigger_name的外键
       trigger_group: qrtz_triggers表trigger_group的外键
       cron_expression:cron表达式
      
       表qrtz_scheduler_state:存储集群中note实例信息,quartz会定时读取该表的信息判断集群中每个实例的当前状态
       instance_name:之前配置文件中org.quartz.scheduler.instanceId配置的名字,就会写入该字段,如果设置为AUTO,quartz会根据物理机名和当前时间产生一个名字
       last_checkin_time:上次检查时间
       checkin_interval:检查间隔时间

配置数据库连接池
1.配置jdbc.properties文件
#mysql database setting
quartz.jdbc.driver=com.mysql.jdbc.Driver
quartz.jdbc.url=jdbc:mysql://10.10.46.145:3306/test?useUnicode=true&characterEncoding=utf-8
quartz.jdbc.username=root
quartz.jdbc.password=root

2.配置applicationContext.xml文件
		<bean id="quartzDataSource" class="org.springframework.jdbc.datasource.SimpleDriverDataSource">
			<property name="driverClass" value="${quartz.jdbc.driver}" />
			<property name="url" value="${quartz.jdbc.url}" />
			<property name="username" value="${quartz.jdbc.username}" />
			<property name="password" value="${quartz.jdbc.password}" />
		</bean>


3.applicationContext-quartz-timer-cluster.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:util="http://www.springframework.org/schema/util"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
						http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd"
	default-lazy-init="true">

	<description>Quartz的定时集群任务配置</description>

	<!-- Quartz集群Schduler -->
	<bean id="clusterQuartzScheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
		<!-- Triggers集成 -->
		<property name="triggers">
			<list>
				<ref bean="timerTrigger" />
			</list>
		</property>
		<!--  quartz配置文件路径-->
		<property name="configLocation" value="classpath:schedule/quartz-cluster.properties" />
		<!-- 启动时延期3秒开始任务 -->
		<property name="startupDelay" value="3" />
		<!-- 保存Job数据到数据库所需的数据源 -->
		<property name="dataSource" ref="quartzDataSource" />
		<!-- Job接受applicationContext的成员变量名 -->
		<property name="applicationContextSchedulerContextKey" value="applicationContext" />
	</bean>

	<!-- Timer式 Trigger定义-->
	<bean id="timerTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean">
		<property name="jobDetail" ref="timerJobDetail" />
		<property name="repeatInterval" value="120000" />
	</bean>

	<!-- 
	<bean id="timerTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
		<property name="jobDetail" ref="timerJobDetail" />
		<property name="cronExpression" value="0 0/2 * * * ?" />
	</bean> -->

	<!-- Timer JobDetail, 基于JobDetailBean实例化Job Class,可持久化到数据库实现集群 -->
	<bean id="timerJobDetail" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
		<property name="jobClass" value="com.test.schedule.QuartzClusterableJob" />
	</bean>

	<!-- Timer Job的可配置属性,在job中通过applicationContext动态获取 -->
	<util:map id="timerJobConfig">
		<entry key="nodeName" value="default" />
	</util:map>
</beans>

dataSource:项目中用到的数据源,里面包含了quartz用到的11张数据库表;
applicationContextSchedulerContextKey: 是org.springframework.scheduling.quartz.SchedulerFactoryBean这个类中把spring上下 文以key/value的方式存放在了quartz的上下文中了,可以用applicationContextSchedulerContextKey所 定义的key得到对应的spring上下文;
configLocation:用于指明quartz的配置文件的位置

4.quartz-cluster.properties
#============================================================================
# Configure Main Scheduler Properties 
#============================================================================
org.quartz.scheduler.instanceName = ClusteredScheduler
org.quartz.scheduler.instanceId = AUTO
org.quartz.scheduler.skipUpdateCheck = true

#============================================================================
# Configure ThreadPool 
#============================================================================
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount = 5
org.quartz.threadPool.threadPriority = 5

#============================================================================
# Configure JobStore 
#============================================================================
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate
org.quartz.jobStore.misfireThreshold = 60000
org.quartz.jobStore.useProperties = false
org.quartz.jobStore.tablePrefix = QRTZ_

org.quartz.jobStore.isClustered = true
org.quartz.jobStore.clusterCheckinInterval = 15000

org.quartz.scheduler.instanceName属性可为任何值,用在 JDBC JobStore 中来唯一标识实例,但是所有集群节点中必须相同。

org.quartz.scheduler.instanceId 属性为 AUTO即可,基于主机名和时间戳来产生实例 ID。

org.quartz.jobStore.class属性为 JobStoreTX,将任务持久化到数据中。因为集群中节点依赖于数据库来传播 Scheduler 实例的状态,你只能在使用 JDBC JobStore 时应用 Quartz 集群。这意味着你必须使用 JobStoreTX 或是 JobStoreCMT 作为 Job 存储;你不能在集群中使用 RAMJobStore。

org.quartz.jobStore.isClustered 属性为 true,你就告诉了 Scheduler 实例要它参与到一个集群当中。这一属性会贯穿于调度框架的始终,用于修改集群环境中操作的默认行为。

org.quartz.jobStore.clusterCheckinInterval 属性定义了Scheduler 实例检入到数据库中的频率(单位:毫秒)。Scheduler 检查是否其他的实例到了它们应当检入的时候未检入;这能指出一个失败的 Scheduler 实例,且当前 Scheduler 会以此来接管任何执行失败并可恢复的 Job。通过检入操作,Scheduler 也会更新自身的状态记录。clusterChedkinInterval 越小,Scheduler 节点检查失败的 Scheduler 实例就越频繁。默认值是 15000 (即15 秒)。
5.QuartzClusterableJob.java
/**
 * 被Spring的Quartz JobDetailBean定时执行的Job类, 支持持久化到数据库实现Quartz集群.
 * 
 * 因为需要被持久化,只能在每次调度时从QuartzJobBean注入的applicationContext中动态    取出.
 */
public class QuartzClusterableJob extends QuartzJobBean {

	private ApplicationContext applicationContext;

	/**
	 * 从SchedulerFactoryBean注入的applicationContext.
	 */
	public void setApplicationContext(ApplicationContext applicationContext) {
		this.applicationContext = applicationContext;
	}

	@Override
	protected void executeInternal(JobExecutionContext ctx) throws JobExecutionException {
		Map config = (Map) applicationContext.getBean("timerJobConfig");
		String nodeName = (String) config.get("nodeName");
		System.out.println("quartz cluster job on node "+nodeName+" .");
	}
}


Quartz 实际并不关心你是在相同的还是不同的机器上运行节点。当集群是放置在不同的机器上时,通常称之为水平集群。节点是跑在同一台机器是,称之为垂直集群。对于垂直集群,存在着单点故障的问题。这对高可用性的应用来说是个坏消息,因为一旦机器崩溃了,所有的节点也就被有效的终止了。

当你运行水平集群时,时钟应当要同步,以免出现离奇且不可预知的行为。假如时钟没能够同步,Scheduler 实例将对其他节点的状态产生混乱。有几种简单的方法来保证时钟何持同步,而且也没有理由不这么做。最简单的同步计算机时钟的方式是使用某一个 Internet 时间服务器(Internet Time Server ITS)。

没什么会阻止你在相同环境中使用集群的和非集群的 Quartz 应用。唯一要注意的是这两个环境不要混用在相同的数据库表。意思是非集群环境不要使用与集群应用相同的一套数据库表;否则将得到希奇古怪的结果,集群和非集群的 Job 都会遇到问题。

假如你让一个非集群的 Quartz 应用与集群节点并行着运行,设法使用 JobInitializationPlugin和 RAMJobStore。

注:例子中使用的是mysql数据库,还要解决水平集群时不同机器通过ip访问mysql的问题
在mysql数据库服务器中
进入:mysql -u root -p/mysql -h localhost -u root -p mysql;
授权:grant all privileges on   *.* to root@"%" identified by 'root' with grant option;
flush privileges;

它的意思是给从任意ip地址连接的用户名为root,密码为root的用户赋予所有的权限。其中的"%"为任意的ip地址,如果想设为特定的值也可以设定为特定的值。
分享到:
评论
2 楼 super3949 2013-07-01  
再补充一下,他们那里用的MethodInvokingJobDetailFactoryBean,是在spring2.x中的,你这里是3.x。难道是spring3.x已经提供那个功能了么,求解释
1 楼 super3949 2013-07-01  
你好,请问你一个问题,MethodInvokingJobDetailFactoryBean 我见其他地方好多用的都是第三方写的,可以解释一下么

相关推荐

    Spring+Quartz 集群

    5. **集群配置**:为了实现高可用的Quartz集群,你需要配置多个节点共享同一个数据库存储的作业和触发器信息。Quartz支持多种持久化策略,如JDBC、RAMJobStore等,选择数据库存储能保证在集群中的任务状态一致性。 ...

    spring + quartz 集群配置

    java + quartz实现定时任务,实现集群配置,在集群环境下多节点运行定时Quartz定任务,就会存在重复处理任务的现象,为解决这一问题,下面我将介绍使用 Quartz 的 TASK ( 12 张表)实例化到数据库,基于数据库自动...

    Spring+Quartz集群部署案例

    最近项目中使用了spring+Quartz定时任务、但是项目最近要集群部署、多个APP下如何利用Quartz 协调处理任务。 大家可以思考一下、现在有 A、B、C三个应用同时作为集群服务器对外统一提供服务、每个应用下各有一个...

    spring+quartz定时集群支持

    至于数据库,Quartz集群需要一个共享的数据库存储job和trigger的信息,这就是`dbTables`文件所涉及的内容。Quartz会在数据库中创建一系列的表,用于存储任务元数据,如job信息、trigger信息等。这些表的设计和初始化...

    定时框架spring+quartz

    "定时框架spring+quartz"的结合,就是将Quartz的定时功能与Spring的强大集成能力完美融合,为开发者提供了一种高效、灵活的定时任务解决方案。 Spring框架提供了多种方式来管理定时任务,包括使用Spring的`@...

    spring3+quartz1.6.4 集群示例

    在Quartz集群中,多个Quartz服务器节点共享同一个作业和触发器的信息,当一个节点失败时,其他节点可以接管任务执行,确保服务的连续性。Quartz使用数据库存储作业和触发器的状态,实现集群间的同步。 4. **Spring...

    Spring+quartz相关jar包.rar

    Quartz 还具有集群功能,可以确保在多服务器环境中任务的可靠执行。 当 Spring 与 Quartz 结合使用时,Spring 可以通过其强大的容器管理和配置能力,将 Quartz 集成到应用程序中。例如,Spring 提供了 `org.spring...

    spring boot + quartz集群搭建的完整步骤

    Spring Boot + Quartz 集群搭建的完整步骤 Spring Boot 是一个流行的 Java 框架,用于快速构建基于 Spring 的应用程序。Quartz 是一个流行的开源作业调度框架,可以用于实现定时任务的调度。 Spring Boot + Quartz ...

    Spring+Quartz定时调度

    - **集群支持**:Quartz支持多节点集群,当一个节点失败时,任务可以由其他节点接管。 - **Job持久化**:Quartz可以通过JDBC或RAMJobStore等方式持久化Job,保证任务不会因应用重启而丢失。 - **Job状态管理**:...

    Spring + quartz 定时任务修改定时时间不重启服务

    Spring + quartz 定时任务修改定时时间不重启服务

    SSH框架+Quartz集群

    在压缩包文件"oa_ssh"中,可能包含了项目的所有源代码、配置文件、数据库脚本等资源,开发者可以通过这些文件了解和学习SSH框架与Quartz集群的整合实现,以及RABC权限管理的具体细节。通过研究和实践,可以深入理解...

    Spring+Quartz 从数据库中获取定时任务和定时时间,动态实现对定时任务的增删改查

    Quartz支持从数据库存储作业和触发器,这样可以方便地进行任务的持久化和集群环境下的任务同步。 1. **Spring与Quartz的集成**:Spring提供了与Quartz的无缝集成,通过`Spring-Job`和`Spring-Trigger`接口,我们...

    spring boot + quartz 动态管理 分布式

    在IT行业中,Spring Boot和Quartz是两个非常重要的框架,它们在企业级应用开发中扮演着关键角色。Spring Boot简化了Spring应用的初始搭建以及开发过程,提供了开箱即用的功能,而Quartz则是一个强大的任务调度库,常...

    spring4.0.6+quartz 2.2.3 集群示例

    本文将详细讲解如何结合Spring 4.0.6版本和Quartz 2.2.3版本来实现一个集群示例,帮助你理解和掌握相关知识点。 首先,让我们了解Spring 4.0.6。这是Spring框架的一个稳定版本,提供了许多增强功能和性能优化。...

    11-Spring+Quartz定时任务最简集群版1

    为了实现Quartz集群,还需要注意以下几点: 1. 数据源配置:确保Quartz能够访问一个共享的数据源,以便所有节点可以读写相同的调度信息。 2. 集群节点ID(instanceId):每个节点的instanceId应不同,以区分不同的...

    spring4+hibernate5+quartz2+hdfs整合

    Quartz 2 提供了更稳定、更健壮的调度功能,支持集群环境,可以在分布式系统中协调任务执行。它可以用来安排任务的触发,如定时发送邮件、执行数据清理等。Quartz 2 的API允许开发者方便地创建、修改和删除作业及...

    spring集成quartz集群配置

    在IT行业中,Spring框架是Java应用开发中的基石,而Quartz则是广泛...通过上述步骤,你已经掌握了Spring集成Quartz集群配置的基本概念。在实践中,根据具体需求调整配置,可以实现高效、稳定且可扩展的任务调度系统。

    quartz整合springbatch动态集群定时实现mysql参考

    在这个“quartz_springbatch_dynamic”项目中,我们将看到如何将这两个强大的工具结合起来,以实现动态集群环境中的定时任务执行,并使用MySQL作为数据存储。 Quartz是一个开源的作业调度框架,允许开发者创建、...

    quartz+spring分布式集群

    - 考虑使用监控工具(如Prometheus+Grafana)监控Quartz集群的运行状态,以便及时发现和解决问题。 通过以上知识点的学习和实践,开发者可以熟练掌握在Spring环境中使用Quartz实现分布式集群的作业调度,提升系统...

    spring 集成quartz 用数据库实现quartz的集群

    【Spring集成Quartz定时任务与数据库实现集群详解】 在企业级应用中,定时任务的管理是必不可少的一部分,Spring框架提供了与Quartz的集成,使得我们可以方便地创建和管理定时任务。Quartz是一款强大的、开放源代码...

Global site tag (gtag.js) - Google Analytics