quartz集群分布式(并发)部署解决方案-Spring

项目中使用分布式并发部署定时任务,多台跨JVM,按照常理逻辑每个JVM的定时任务会各自运行,这样就会存在问题,多台分布式JVM机器的应用服务同时干活,一个是加重服务负担,另外一个是存在严重的逻辑问题,比如需要回滚的数据,就回滚了多次,刚好quartz提供很好的解决方案。

集群分布式并发环境中使用QUARTZ定时任务调度,会在各个节点会上报任务,存到数据库中,执行时会从数据库中取出触发器来执行,如果触发器的名称和执行时间相同,则只有一个节点去执行此任务。

如果此节点执行失败,则此任务则会被分派到另一节点执行,中途也会自动检查失效的定时调度,发现不成功的,其他节点立马接过来继续完成定时任务。对应的定时任务调度表比较多,有11个。

此方法是结合Spring与quartz,实际解决方案如下:

####applicationContext-scheduler.xml###  spring 3.11

<?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:context="http://www.springframework.org/schema/context"
  xmlns:task="http://www.springframework.org/schema/task"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
            http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context-3.2.xsd
            http://www.springframework.org/schema/task
            http://www.springframework.org/schema/task/spring-task-3.2.xsd">

  <context:annotation-config />
  <context:component-scan base-package="com.dennis.walking.api.web.schedule" />

  <bean id="rollbackOrderStatus" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
    <property name="jobClass" value="com.dennis.walking.api.web.schedule.ReleaseQtyAndUpdateOrderStatusSchedule" />
    <property name="durability" value="true" />
  </bean>
  <bean id="rollbackOrderStatusTrigger" class="com.dennis.walking.api.web.schedule.PersistableCronTriggerFactoryBean">
    <property name="jobDetail" ref="rollbackOrderStatus" />
    <property name="cronExpression">
      <value>0 0/5 * * * ?</value>
    </property>
    <property name="timeZone">
      <value>GMT+8:00</value>
    </property>
  </bean>

  <bean id="quartzScheduler" parent="baseQuartzScheduler">
    <property name="configLocation" value="classpath:quartz.properties" />
    <property name="autoStartup" value="true" />
    <!-- This name is persisted as SCHED_NAME in db. for local testing could change to unique name to avoid collision with dev server -->
    <property name="schedulerName" value="apiQuartzScheduler" />
    <!-- NOTE: Must add both the jobDetail and trigger to the scheduler! -->
    <property name="triggers">
      <list>
        <ref bean="rollbackOrderStatusTrigger" />
      </list>
    </property>

    <property name="jobDetails">
      <list>
        <ref bean="rollbackOrderStatus" />
      </list>
    </property>
  </bean>

  <bean id="baseQuartzScheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
    <!--
    <property name="configLocation" value="classpath:quartz.properties" />
     -->
    <property name="dataSource" ref="dataSource" />
    <property name="transactionManager" ref="transManager" />

    <!-- This name is persisted as SCHED_NAME in db. for local testing could change to unique name to avoid collision with dev server -->
    <property name="schedulerName" value="quartzScheduler" />

    <!-- Will update database cron triggers to what is in this jobs file on each deploy. Replaces all previous trigger and job data that was in the database. YMMV -->
    <property name="overwriteExistingJobs" value="true" />
    <!--
    <property name="autoStartup" value="true" />
     -->
    <property name="applicationContextSchedulerContextKey" value="applicationContext" />
    <property name="jobFactory">
      <bean class="com.dennis.walking.api.web.schedule.AutowiringSpringBeanJobFactory" />
    </property>
    <!-- NOTE: Must add both the jobDetail and trigger to the scheduler! -->
    <!--
    <property name="jobDetails">
      <list>
      </list>
    </property>
    <property name="triggers">
      <list>
      </list>
    </property>
    -->
  </bean>
</beans>

记得对应下面的三个类文件。

###quartz.properties###

# Using Spring datasource in quartzJobsConfig.xml
# Spring uses LocalDataSourceJobStore extension of JobStoreCMT
org.quartz.jobStore.useProperties=true
org.quartz.jobStore.tablePrefix=QRTZ_
org.quartz.jobStore.isClustered=true
# 10 mins
org.quartz.jobStore.clusterCheckinInterval=600000
org.quartz.scheduler.skipUpdateCheck=true

# Change this to match your DB vendor
org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate
# Needed to manage cluster instances
org.quartz.scheduler.instanceId=AUTO
org.quartz.scheduler.instanceName=MY_JOB_SCHEDULER

org.quartz.scheduler.rmi.export=false
org.quartz.scheduler.rmi.proxy=false
org.quartz.threadPool.class=org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount=10
org.quartz.threadPool.threadPriority=5
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread=true

# Configure Plugins
org.quartz.plugin.triggHistory.class =   org.quartz.plugins.history.LoggingTriggerHistoryPlugin
org.quartz.plugin.triggHistory.triggerFiredMessage =   Trigger \{1\}.\{0\} fired job \{6\}.\{5\} at: \{4, date, HH:mm:ss MM/dd/yyyy}
org.quartz.plugin.triggHistory.triggerCompleteMessage =   Trigger \{1\}.\{0\} completed firing job \{6\}.\{5\} at \{4, date, HH:mm:ss MM/dd/yyyy\}.

quartz定时调度常用时间点设置

"0 0 12 * * ?"                     Fire at 12pm (noon) every day
"0 15 10 ? * *"                   Fire at 10:15am every day
"0 15 10 * * ?"                   Fire at 10:15am every day
"0 15 10 * * ? *"                 Fire at 10:15am every day
"0 15 10 * * ? 2005"           Fire at 10:15am every day during the year 2005
"0 * 14 * * ?"                     Fire every minute starting at 2pm and ending at 2:59pm, every day
"0 0/5 14 * * ?"                  Fire every 5 minutes starting at 2pm and ending at 2:55pm, every day
"0 0/5 14,18 * * ?"              Fire every 5 minutes starting at 2pm and ending at 2:55pm, AND fire every 5 minutes starting at 6pm and ending at 6:55pm, every day
"0 0-5 14 * * ?"                   Fire every minute starting at 2pm and ending at 2:05pm, every day
"0 10,44 14 ? 3 WED"         Fire at 2:10pm and at 2:44pm every Wednesday in the month of March.
"0 15 10 ? * MON-FRI"        Fire at 10:15am every Monday, Tuesday, Wednesday, Thursday and Friday
"0 15 10 15 * ?"                  Fire at 10:15am on the 15th day of every month
"0 15 10 L * ?"                    Fire at 10:15am on the last day of every month
"0 15 10 ? * 6L"                   Fire at 10:15am on the last Friday of every month
"0 15 10 ? * 6L"                   Fire at 10:15am on the last Friday of every month
"0 15 10 ? * 6L 2002-2005"   Fire at 10:15am on every last Friday of every month during the years 2002, 2003, 2004 and 2005
"0 15 10 ? * 6#3"                 Fire at 10:15am on the third Friday of every month

真实运行的业务类:ReleaseQtyAndUpdateOrderStatusSchedule.java

应为要持久化等特性操作,需要继承 QuartzJobBean

由于要被持久化,所以不能存放xxxxManager类似对象,

只能从每次从QuartzJobBean注入的ApplicationContext 中去取出

继承QuartzJobBean,实现方法executeInternal

package com.dennis.walking.api.web.schedule;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.QuartzJobBean;
import org.springframework.stereotype.Component;
import com.dennis.walking.api.service.OrderService;

@Component
public class ReleaseQtyAndUpdateOrderStatusSchedule extends QuartzJobBean {

  private Log log = LogFactory.getLog(this.getClass());

  @Autowired
  OrderService orderService;

  protected void executeInternal(JobExecutionContext arg0)
      throws JobExecutionException {
    log.info("dennis test execute schedule start ");
    try {
      orderService.releaseQtyAndUpdateOrderStatus();
    } catch (Exception e) {
      e.printStackTrace();
      log.error("execute ReleaseQtyAndUpdateOrderStatus schedule error:"
          + e.getMessage());
    }
    log.info("dennis test exxcute schedule end");
  }
}

持久化数据:PersistableCronTriggerFactoryBean.java  保存数据到数据库中

package com.dennis.walking.api.web.schedule;

import org.springframework.scheduling.quartz.CronTriggerFactoryBean;
import org.springframework.scheduling.quartz.JobDetailAwareTrigger;

/**
 * Needed to set Quartz useProperties=true when using Spring classes, because
 * Spring sets an object reference on JobDataMap that is not a String
 *
 * @see http://site.trimplement.com/using-spring-and-quartz-with-jobstore-properties
 *      /
 * @see http
 *      ://forum.springsource.org/showthread.php?130984-Quartz-error-IOException
 */
public class PersistableCronTriggerFactoryBean extends CronTriggerFactoryBean {
  @Override
  public void afterPropertiesSet() {
    super.afterPropertiesSet();
    System.out.println("PersistableCronTriggerFactoryBean-------------------");
    // Remove the JobDetail element
    getJobDataMap().remove(JobDetailAwareTrigger.JOB_DETAIL_KEY);
  }
}

###AutowiringSpringBeanJobFactory.java### 使用spring的 bean文件时,需要使用此类

package com.dennis.walking.api.web.schedule;

import org.quartz.spi.TriggerFiredBundle;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.scheduling.quartz.SpringBeanJobFactory;

/**
 * Autowire Quartz Jobs with Spring context dependencies
 *
 * @see http
 *      ://stackoverflow.com/questions/6990767/inject-bean-reference-into-a-quartz
 *      -job-in-spring/15211030#15211030
 */
public final class AutowiringSpringBeanJobFactory extends SpringBeanJobFactory
    implements ApplicationContextAware {

  private transient AutowireCapableBeanFactory beanFactory;

  public void setApplicationContext(final ApplicationContext context) {
    beanFactory = context.getAutowireCapableBeanFactory();
  }

  @Override
  protected Object createJobInstance(final TriggerFiredBundle bundle)
      throws Exception {
    final Object job = super.createJobInstance(bundle);
    beanFactory.autowireBean(job);
    System.out.println("AutowiringSpringBeanJobFactory-------------------");
    return job;
  }
}

###tables_mysql.sql###  需要建立的11张表

#
# Quartz seems to work best with the driver mysql-connector-java-5.1.34-bin.jar
#
# PLEASE consider using mysql with innodb tables to avoid locking issues
#
# In your Quartz properties file, you‘ll need to set
# org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
#

DROP TABLE IF EXISTS QRTZ_FIRED_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_PAUSED_TRIGGER_GRPS;
DROP TABLE IF EXISTS QRTZ_SCHEDULER_STATE;
DROP TABLE IF EXISTS QRTZ_LOCKS;
DROP TABLE IF EXISTS QRTZ_SIMPLE_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_SIMPROP_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_CRON_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_BLOB_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_JOB_DETAILS;
DROP TABLE IF EXISTS QRTZ_CALENDARS;

CREATE TABLE QRTZ_JOB_DETAILS
  (
    SCHED_NAME VARCHAR(120) NOT NULL,
    JOB_NAME  VARCHAR(200) NOT NULL,
    JOB_GROUP VARCHAR(200) NOT NULL,
    DESCRIPTION VARCHAR(250) NULL,
    JOB_CLASS_NAME   VARCHAR(250) NOT NULL,
    IS_DURABLE VARCHAR(1) NOT NULL,
    IS_NONCONCURRENT VARCHAR(1) NOT NULL,
    IS_UPDATE_DATA VARCHAR(1) NOT NULL,
    REQUESTS_RECOVERY VARCHAR(1) NOT NULL,
    JOB_DATA BLOB NULL,
    PRIMARY KEY (SCHED_NAME,JOB_NAME,JOB_GROUP)
);

CREATE TABLE QRTZ_TRIGGERS
  (
    SCHED_NAME VARCHAR(120) NOT NULL,
    TRIGGER_NAME VARCHAR(200) NOT NULL,
    TRIGGER_GROUP VARCHAR(200) NOT NULL,
    JOB_NAME  VARCHAR(200) NOT NULL,
    JOB_GROUP VARCHAR(200) NOT NULL,
    DESCRIPTION VARCHAR(250) NULL,
    NEXT_FIRE_TIME BIGINT(13) NULL,
    PREV_FIRE_TIME BIGINT(13) NULL,
    PRIORITY INTEGER NULL,
    TRIGGER_STATE VARCHAR(16) NOT NULL,
    TRIGGER_TYPE VARCHAR(8) NOT NULL,
    START_TIME BIGINT(13) NOT NULL,
    END_TIME BIGINT(13) NULL,
    CALENDAR_NAME VARCHAR(200) NULL,
    MISFIRE_INSTR SMALLINT(2) NULL,
    JOB_DATA BLOB NULL,
    PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
    FOREIGN KEY (SCHED_NAME,JOB_NAME,JOB_GROUP)
        REFERENCES QRTZ_JOB_DETAILS(SCHED_NAME,JOB_NAME,JOB_GROUP)
);

CREATE TABLE QRTZ_SIMPLE_TRIGGERS
  (
    SCHED_NAME VARCHAR(120) NOT NULL,
    TRIGGER_NAME VARCHAR(200) NOT NULL,
    TRIGGER_GROUP VARCHAR(200) NOT NULL,
    REPEAT_COUNT BIGINT(7) NOT NULL,
    REPEAT_INTERVAL BIGINT(12) NOT NULL,
    TIMES_TRIGGERED BIGINT(10) NOT NULL,
    PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
    FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
        REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
);

CREATE TABLE QRTZ_CRON_TRIGGERS
  (
    SCHED_NAME VARCHAR(120) NOT NULL,
    TRIGGER_NAME VARCHAR(200) NOT NULL,
    TRIGGER_GROUP VARCHAR(200) NOT NULL,
    CRON_EXPRESSION VARCHAR(200) NOT NULL,
    TIME_ZONE_ID VARCHAR(80),
    PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
    FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
        REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
);

CREATE TABLE QRTZ_SIMPROP_TRIGGERS
  (
    SCHED_NAME VARCHAR(120) NOT NULL,
    TRIGGER_NAME VARCHAR(200) NOT NULL,
    TRIGGER_GROUP VARCHAR(200) NOT NULL,
    STR_PROP_1 VARCHAR(512) NULL,
    STR_PROP_2 VARCHAR(512) NULL,
    STR_PROP_3 VARCHAR(512) NULL,
    INT_PROP_1 INT NULL,
    INT_PROP_2 INT NULL,
    LONG_PROP_1 BIGINT NULL,
    LONG_PROP_2 BIGINT NULL,
    DEC_PROP_1 NUMERIC(13,4) NULL,
    DEC_PROP_2 NUMERIC(13,4) NULL,
    BOOL_PROP_1 VARCHAR(1) NULL,
    BOOL_PROP_2 VARCHAR(1) NULL,
    PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
    FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
    REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
);

CREATE TABLE QRTZ_BLOB_TRIGGERS
  (
    SCHED_NAME VARCHAR(120) NOT NULL,
    TRIGGER_NAME VARCHAR(200) NOT NULL,
    TRIGGER_GROUP VARCHAR(200) NOT NULL,
    BLOB_DATA BLOB NULL,
    PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
    FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
        REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
);

CREATE TABLE QRTZ_CALENDARS
  (
    SCHED_NAME VARCHAR(120) NOT NULL,
    CALENDAR_NAME  VARCHAR(200) NOT NULL,
    CALENDAR BLOB NOT NULL,
    PRIMARY KEY (SCHED_NAME,CALENDAR_NAME)
);

CREATE TABLE QRTZ_PAUSED_TRIGGER_GRPS
  (
    SCHED_NAME VARCHAR(120) NOT NULL,
    TRIGGER_GROUP  VARCHAR(200) NOT NULL,
    PRIMARY KEY (SCHED_NAME,TRIGGER_GROUP)
);

CREATE TABLE QRTZ_FIRED_TRIGGERS
  (
    SCHED_NAME VARCHAR(120) NOT NULL,
    ENTRY_ID VARCHAR(95) NOT NULL,
    TRIGGER_NAME VARCHAR(200) NOT NULL,
    TRIGGER_GROUP VARCHAR(200) NOT NULL,
    INSTANCE_NAME VARCHAR(200) NOT NULL,
    FIRED_TIME BIGINT(13) NOT NULL,
    SCHED_TIME BIGINT(13) NOT NULL,
    PRIORITY INTEGER NOT NULL,
    STATE VARCHAR(16) NOT NULL,
    JOB_NAME VARCHAR(200) NULL,
    JOB_GROUP VARCHAR(200) NULL,
    IS_NONCONCURRENT VARCHAR(1) NULL,
    REQUESTS_RECOVERY VARCHAR(1) NULL,
    PRIMARY KEY (SCHED_NAME,ENTRY_ID)
);

CREATE TABLE QRTZ_SCHEDULER_STATE
  (
    SCHED_NAME VARCHAR(120) NOT NULL,
    INSTANCE_NAME VARCHAR(200) NOT NULL,
    LAST_CHECKIN_TIME BIGINT(13) NOT NULL,
    CHECKIN_INTERVAL BIGINT(13) NOT NULL,
    PRIMARY KEY (SCHED_NAME,INSTANCE_NAME)
);

CREATE TABLE QRTZ_LOCKS
  (
    SCHED_NAME VARCHAR(120) NOT NULL,
    LOCK_NAME  VARCHAR(40) NOT NULL,
    PRIMARY KEY (SCHED_NAME,LOCK_NAME)
);

commit;

###如果定时任务比较多,建议增加索引提升速度。
/*
reate index idx_qrtz_j_req_recovery on qrtz_job_details(SCHED_NAME,REQUESTS_RECOVERY);
create index idx_qrtz_j_grp on qrtz_job_details(SCHED_NAME,JOB_GROUP);
create index idx_qrtz_t_j on qrtz_triggers(SCHED_NAME,JOB_NAME,JOB_GROUP);
create index idx_qrtz_t_jg on qrtz_triggers(SCHED_NAME,JOB_GROUP);
create index idx_qrtz_t_c on qrtz_triggers(SCHED_NAME,CALENDAR_NAME);
create index idx_qrtz_t_g on qrtz_triggers(SCHED_NAME,TRIGGER_GROUP);
create index idx_qrtz_t_state on qrtz_triggers(SCHED_NAME,TRIGGER_STATE);
create index idx_qrtz_t_n_state on qrtz_triggers(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP,TRIGGER_STATE);
create index idx_qrtz_t_n_g_state on qrtz_triggers(SCHED_NAME,TRIGGER_GROUP,TRIGGER_STATE);
create index idx_qrtz_t_next_fire_time on qrtz_triggers(SCHED_NAME,NEXT_FIRE_TIME);
create index idx_qrtz_t_nft_st on qrtz_triggers(SCHED_NAME,TRIGGER_STATE,NEXT_FIRE_TIME);
create index idx_qrtz_t_nft_misfire on qrtz_triggers(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME);
create index idx_qrtz_t_nft_st_misfire on qrtz_triggers(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_STATE);
create index idx_qrtz_t_nft_st_misfire_grp on qrtz_triggers(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_GROUP,TRIGGER_STATE);
create index idx_qrtz_ft_trig_inst_name on qrtz_fired_triggers(SCHED_NAME,INSTANCE_NAME);
create index idx_qrtz_ft_inst_job_req_rcvry on qrtz_fired_triggers(SCHED_NAME,INSTANCE_NAME,REQUESTS_RECOVERY);
create index idx_qrtz_ft_j_g on qrtz_fired_triggers(SCHED_NAME,JOB_NAME,JOB_GROUP);
create index idx_qrtz_ft_jg on qrtz_fired_triggers(SCHED_NAME,JOB_GROUP);
create index idx_qrtz_ft_t_g on qrtz_fired_triggers(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP);
create index idx_qrtz_ft_tg on qrtz_fired_triggers(SCHED_NAME,TRIGGER_GROUP);
*/

本文测试软件环境使用的jar版本是:

quartz-2.2.1.jar mysql-connector-java-5.1.34.jar

linux apache-tomcat-7.0.47 ava version "1.7.0_72" 64位

windows7  java version "1.7.0_45"  64位 jetty

Quartz是一个开放源码项目,专注于任务调度器,提供了极为广泛的特性如持久化任务,集群和分布式任务等。 Quartz核心是调度器,还采用多线程管理。

1.持久化任务:当应用程序停止运行时,所有调度信息不被丢失,当你重新启动时,调度信息还存在,这就是持久化任务(保存到数据库表中)。

2.集群和分布式处理:当在集群环境下,当有配置Quartz的多个客户端时(节点),采用Quartz的集群和分布式处理时,我们要了解几点好处

1) 一个节点无法完成的任务,会被集群中拥有相同的任务的节点取代执行。

2) Quartz调度是通过触发器的类别来识别不同的任务,在不同的节点定义相同的触发器的类别,这样在集群下能稳定的运行,一个节点无法完成的任务,会被集群中拥有相同的任务的节点取代执行。

3)分布式体现在当相同的任务定时在一个时间点,在那个时间点,不会被两个节点同时执行。

Quartz的 Task(11 张表)实例化采用数据库存储,基于数据库引擎及 High-Available 的策略(集群的一种策略)自动协调每个节点的 Quartz。

时间: 2024-10-12 05:21:13

quartz集群分布式(并发)部署解决方案-Spring的相关文章

教你如何利用分布式的思想处理集群的参数配置信息——spring的configurer妙用

引言 最近LZ的技术博文数量直线下降,实在是非常抱歉,之前LZ曾信誓旦旦的说一定要把<深入理解计算机系统>写完,现在看来,LZ似乎是在打自己脸了.尽管LZ内心一直没放弃,但从现状来看,需要等LZ的PM做的比较稳定,时间慢慢空闲出来的时候才有机会看了.短时间内,还是要以解决实际问题为主,而不是增加自己其它方面的实力. 因此,本着解决实际问题的目的,LZ就研究出一种解决当下问题的方案,可能文章的标题看起来挺牛B的,其实LZ就是简单的利用了一下分布式的思想,以及spring框架的特性,解决了当下的参

集群环境下定时调度的解决方案之Quartz集群

集群环境可能出现的问题 在上一篇博客我们介绍了如何在自己的项目中从无到有的添加了Quartz定时调度引擎,其实就是一个Quartz 和Spring的整合过程,很容易实现,但是我们现在企业中项目通常都是部署在集群环境中的,这样我们之前的定时调度就会出现问题了,因为我们的定时任务都加载在内存中的,每个集群节点中的调度器都会去执行,这就会存在重复执行和资源竞争的问题,那么如何来解决这样的问题呢,往下面看吧... 解决方案 在一般的企业中解决类似的问题一般都是在一个note上部署Quartz其他note

Spring+quartz集群配置,Spring定时任务集群,quartz定时任务集群

Spring+quartz集群配置,Spring定时任务集群,quartz定时任务集群 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 蕃薯耀 2016年7月7日 09:06:09 星期四 http://fanshuya

spring quartz 集群配置

Quartz 是一个开源的作业调度框架,它完全由 Java 写成,并设计用于 J2SE 和 J2EE 应用中.它提供了巨大的灵活性而不牺牲简单性.你能够用它来为执行一个作业而创建简单的或复杂的调度. 在项目中有大量的后台任务需要调度执行,如构建索引.统计报表.周期同步数据等等,要求任务调度系统具备高可用性.负载均衡特性,使用Quartz 会很方便. 下文是spring和quartz进行整合,同时支持集群部署.quartz集群的支持是通过数据库进行任务调度的感知. 1.使用的版本情况:spring

(4) Spring中定时任务Quartz集群配置学习

原 来配置的Quartz是通过spring配置文件生效的,发现在非集群式的服务器上运行良好,但是将工程部署到水平集群服务器上去后改定时功能不能正常运 行,没有任何错误日志,于是从jar包.JDK版本.cronExpression到服务器类型,甚至查到了服务器操作系统的类型,都没能找到解决的办 法,后来才知道是集群惹的祸! 详细步骤如下: 1. 按照Quartz集群工作原理 图:表示了每个节点直接与数据库通信,若离开数据库将对其他节点一无所知 在数据库中建表.建表模版在Quartz包下docs/d

spring boot 整合 quartz 集群环境 实现 动态定时任务配置【原】

最近做了一个spring boot 整合 quartz  实现 动态定时任务配置,在集群环境下运行的 任务.能够对定时任务,动态的进行增删改查,界面效果图如下: 1. 在项目中引入jar 2. 将需要的表导入数据库 官网上有不同数据库的脚本,找到对应的,导入即可 3. java 代码 将quartz 的相关配置文件,配置为暴露bean,方便后期引用. 有一处关键的地方,就是注入spring 上下文,也可以算是一个坑.如果,不注入spring 上下文,那么新添加的定时任务job,是新new 的一个

spring boot + quartz 集群

spring boot bean配置: @Configuration public class QuartzConfig { @Value("${quartz.scheduler.instanceName}") private String quartzInstanceName; @Value("${org.quartz.dataSource.myDS.driver}") private String myDSDriver; @Value("${org.q

Spring+监听器+Quartz集群(1)——基本配置

先说说项目背景,因为业务需求,项目中有很多定时任务,这自然用到了Quartz这个开源产品.而在这之前使用的Quartz主要是基于内存的,在应用程序启动时,由监听器创建定时任务,为了防止多个应用程序重新创建任务,只能在发布时,在另外的web.xml中禁用监听器.这样系统发布变得麻烦,因为不同的应用程序的配置不同. 除了发布麻烦,还有不能发挥集群的优势,一旦运行任务的服务器崩溃,集群中的其他服务器不能接受定时任务. 为了解决以上的两个问题,在系统中使用Quartz集群,同时考虑到系统中创建定时任务的

windows下hadoop的集群分布式部署

下面我们进行说明一下hadoop集群的搭建配置. 本文假设读者具有hadoop单机配置的基础,相同的部分不在重述. 以三台测试机为例搭建一个小集群,三台机器的ip分别为 192.168.200.1;192.168.200.2;192.168.200.3 cygwin,jdk的安装同windows下hadoop的单机伪分布式部署(1),这里略过. 1.配置 hosts 在三台机子的hosts文件中加入如下记录: 192.168.200.1 hadoop1  #master namenode 192