Springboot 定时任务集群(Quartz方式,利用zookeeper实现分布式锁方式)
■1.Quartz方式(Quartz版本:2.2.3)Quartz的定时任务能力比较强大,它自己就可以实现集群功能。Quartz在实现集群功能时,利用了数据库对任务进行调度,而其使用到的数据库表数据都是自动装填的不用认为管理表数据。我们只需要按照Quartz要求建表即可。所需要建表,Quartz已经帮我们写好了SQL,只需要对照你的数据库找到相应的SQL执行一下即可。Quartz官网:ht...
■1.Quartz方式(Quartz版本:2.2.3)
Quartz的定时任务能力比较强大,它自己就可以实现集群功能。Quartz在实现集群功能时,利用了数据库对任务进行调度,而其使用到的数据库表数据都是自动装填的不用认为管理表数据。我们只需要按照Quartz要求建表即可。所需要建表,Quartz已经帮我们写好了SQL,只需要对照你的数据库找到相应的SQL执行一下即可。
Quartz官网:http://www.quartz-scheduler.org/
从官网上直接下载 Quartz 2.2.3 .tar.gz,解压后【quartz-2.2.3/docs/dbTables】下存放各数据库建表的sql文件。
本实例使用的是postgeresql数据库。所以,使用tables_postgres.sql创建所需要的表。
下面是项目代码
A.文件目录结构
B.各文件内容:pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com</groupId>
<artifactId>lpwmsbatch</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<name>lpwmsbatch</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.4.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.8</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.curator/curator-framework -->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>2.12.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.quartz-scheduler/quartz -->
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.2.3</version>
</dependency>
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz-jobs</artifactId>
<version>2.2.3</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
各文件内容:application.properties
# 服务端口
server.port=8080
# Mybatis
spring.profiles.active=dev
mybatis.type-aliases-package=com.infosky.batch.model
mybatis.mapper-locations=classpath*:com/infosky/batch/mapper/*.xml
# 数据源
spring.datasource.url=jdbc:postgresql://xxx.xxx.xxx.xxx:5432/lpaa
spring.datasource.username=test
spring.datasource.password=test
spring.datasource.driver-class-name=org.postgresql.Driver
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true
# ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓Quartz↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
# ============================================================================
# Configure Main Scheduler Properties
# ============================================================================
# 调度标识名 集群中每一个实例都必须使用相同的名称
org.quartz.scheduler.instanceName= TestScheduler
# ID设置为自动获取 每一个必须不同
# 1. 当你想生成intanceId的时候可以设置为AUTO
# 2. 当你想从系统属性org.quartz.scheduler.instanceId取值时可以设置为SYS_PROP
org.quartz.scheduler.instanceId= instance_one
# 生成Schudule实体Id的类,只有在属性org.quartz.scheduler.instanceId设置为AUTO时使用,默认的实现org.quartz.scheduler.SimpleInstanceGenerator是基于主机名称和时间戳生成。其他的实现查看具体的文档
# org.quartz.scheduler.instanceIdGenerator.class
# Scheduler线程的名称
# org.quartz.scheduler.threadName
# 指定Scheduler是否以守护线程(服务)运行
# org.quartz.scheduler.makeSchedulerThreadDaemon
# 当调度程序空闲时,在重新查询可用触发器之前,调度程序将等待毫秒的时间数。不建议少于5000ms,而少于1000是不合法的参数
# org.quartz.scheduler.idleWaitTime
# 使用JobStore(比如连接数据库)时Schueduler检测到失去数据库连接后重新尝试连接的毫秒数
# org.quartz.scheduler.doFailureRetryInterval
# 给Scheduler Context、Job、Trigger的JobDataMaps设置属性值的方式
# org.quartz.scheduler.jobFactory.class
# 键值对,保存在Scheduler Context中,比如有这样的配置org.quartz.shceduler.key.MyKey=MyValue,则在Scheduler Context中赋值方式为scheduler.getContext().put(“MyKey”, “MyValue”
# org.quartz.contenxt.key.SOME_KEY
# 事务管理JNDI URL地址。只有当Quartz使用JobStoreCMT和org.quartz.scheduler.wrapJobExecutionInUserTransaction 设置为true时使用
# org.quartz.scheduler.userTransactionURL
# 只有当你在执行一个Job时想使用UserTransaction时设置为true,参考@ExecuteInJTATransaction 注解
# org.quartz.scheduler.wrapJobExecutionInUserTransaction
# 在同一时间运行Scheduler获取trigger的数量。如果设置的数量>1,并且使用JDBC JobStore,则属性org.quartz.jobStore.acquireTriggersWithinLock应设置为true,可以避破坏数据。
# org.quartz.scheduler.batchTriggerAcquisitionMaxCount
# 运行Scheduler在获取和触发tigger的提前的时间。
# org.quartz.scheduler.batchTriggerAcquisitionFireAheadTimeWindow
# 是否跳过版本检测。可以设置系统参数org.terracotta.quartz.skipUpdateCheck=true或者在JAVA命令行使用-D选项。在正式库运行时应设置为true。
org.quartz.scheduler.skipUpdateCheck= true
# ============================================================================
# Configure ThreadPool
# 线程池配置
# ============================================================================
# 线程池的实现类(一般使用SimpleThreadPool即可满足几乎所有用户的需求)
# Scheduler使用的线程池名称,实现了ThreadPool接口,参考org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.class= org.quartz.simpl.SimpleThreadPool
# 指定线程数,至少为1(无默认值)(一般设置为1-100直接的整数合适)
org.quartz.threadPool.threadCount= 5
# 设置线程的优先级(最大为java.lang.Thread.MAX_PRIORITY 10,最小为Thread.MIN_PRIORITY 1,默认为5)
org.quartz.threadPool.threadPriority= 5
# ============================================================================
# Configure JobStore
# JDBCJobStore和JobStoreTX
# JDBCJobStore和JobStoreTX都使用关系数据库来存储Schedule相关的信息。
# JobStoreTX在每次执行任务后都使用commint或者rollback来提交更改。
# 如果在一个标准的独立应用或者在一个没有使用JTA事务管理的应用中使用Quartz,JDBCJobStore是一个不错的选择。
# ============================================================================
# 信息保存时间 默认值60秒
# 触发器失败后下次触发的时间间隔
org.quartz.jobStore.misfireThreshold= 60000
# 数据保存方式为数据库持久化
org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX
# 使用的数据库驱动,具体的驱动列表详情如下。一般org.quartz.impl.jdbcjobstore.StdJDBCDelegate可以满足大部分数据库
org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.PostgreSQLDelegate
# 使用自己的配置文件
# 配置参数可以被设置为true(默认为false),这样可以指导JDBCJobStore,JobDataMaps中的值都是字符串,因此这样可以以名字-值对存储,而不是存储更加复杂的对象(序列化形式BLOB)。从长远来看,这是很安全的,因为避免了将非字符串类序列化为BLOB的类版本问题。
org.quartz.jobStore.useProperties=false
# 数据库别名 随便取
org.quartz.jobStore.dataSource=myDS
# 表的前缀,默认QRTZ_
org.quartz.jobStore.tablePrefix=QRTZ_
# 是否加入集群
org.quartz.jobStore.isClustered=true
# 检查集群下的其他调度器实体的事件间隔
# org.quartz.jobStore.clusterCheckinInterval
# 如果值为true,就是告诉Quartz(当使用JobStoreTX或CMT)调用JDBC连接的setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE)方法。这可以防止在高负载、持久事务时锁定超时。
# org.quartz.jobStore.txIsolationLevelSerializable
#============================================================================
# Other Example Delegates
#============================================================================
#org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.DB2v6Delegate
#org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.DB2v7Delegate
#org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.DriverDelegate
#org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.HSQLDBDelegate
#org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.MSSQLDelegate
#org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.PointbaseDelegate
#org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.PostgreSQLDelegate
#org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate
#org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.WebLogicDelegate
#org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.oracle.OracleDelegate
#org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.oracle.WebLogicOracleDelegate
#============================================================================
# Configure Datasources
#============================================================================
# 数据库引擎
# 必须是数据库的JDBC驱动的类名
org.quartz.dataSource.myDS.driver= org.postgresql.Driver
# 数据库连接
org.quartz.dataSource.myDS.URL= jdbc:postgresql://xxx.xxx.xxx.xxx:5432/lpaa
org.quartz.dataSource.myDS.user= test
org.quartz.dataSource.myDS.password= test
# 允许最大连接
org.quartz.dataSource.myDS.maxConnections= 5
# SQL查询字符串,数据源用于检测和替换失败或者故障连接
org.quartz.dataSource.myDS.validationQuery= select 0
# 空闲连接测试的时间(单位秒),只有设置了validationQuery属性,才使能。默认值为50秒
# org.quartz.dataSource.NAME.idleConnectionValidationSeconds
# 是否每一次从数据池冲获取连接时,都要去执行数据库SQL查询,以确保连接有效。如果为false,那么在check-in时验证。默认值为false
# org.quartz.dataSource.NAME.validateOnCheckout
# 丢弃连接的超时时间。若值为0,则禁止这个特性。默认值为0
# org.quartz.dataSource.NAME.discardIdleConnectionsSeconds
# 应用服务器管理的数据源的JNDI的URL
# org.quartz.dataSource.NAME.jndiURL
#============================================================================
# Configure Plugins
#============================================================================
#org.quartz.plugin.shutdownHook.class: org.quartz.plugins.management.ShutdownHookPlugin
#org.quartz.plugin.shutdownHook.cleanShutdown: true
#org.quartz.plugin.triggHistory.class: org.quartz.plugins.history.LoggingJobHistoryPlugin
#↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑Quartz↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
各文件内容:SpringBootStartApplication.java
package com.infosky.batch;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@MapperScan("com.infosky.batch.dao")
public class SpringBootStartApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootStartApplication.class, args);
}
}
各文件内容:AutowiringSpringBeanJobFactory.java
package com.infosky.batch.quartz;
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;
public final class AutowiringSpringBeanJobFactory extends SpringBeanJobFactory implements ApplicationContextAware {
private transient AutowireCapableBeanFactory beanFactory;
@Override
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);
return job;
}
}
各文件内容:CheckStatusTask.java
package com.infosky.batch.quartz;
import org.quartz.*;
import org.springframework.stereotype.Component;
@PersistJobDataAfterExecution
@DisallowConcurrentExecution
@Component
public class CheckStatusTask implements Job {
public void execute(JobExecutionContext context) throws JobExecutionException {
// 定时任务逻辑
System.out.println("^^^^^^^^^^^^^");
}
}
各文件内容:QuartzConfig.java
package com.infosky.batch.quartz;
import org.quartz.spi.JobFactory;
import org.springframework.beans.factory.config.PropertiesFactoryBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import java.util.Properties;
/**
* 配置定时任务
*
*/
@Configuration
public class QuartzConfig {
public static final String QUARTZ_PROPERTIES_PATH = "/application.properties";
@Bean
public JobFactory jobFactory(ApplicationContext applicationContext) {
AutowiringSpringBeanJobFactory jobFactory = new AutowiringSpringBeanJobFactory();
jobFactory.setApplicationContext(applicationContext);
return jobFactory;
}
@Bean
public SchedulerFactoryBean schedulerFactoryBean(JobFactory jobFactory) {
SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
schedulerFactoryBean.setJobFactory(jobFactory);
schedulerFactoryBean.setStartupDelay(20);
// 用于quartz集群,加载quartz数据源配置
schedulerFactoryBean.setQuartzProperties(quartzProperties());
return schedulerFactoryBean;
}
public Properties quartzProperties() {
PropertiesFactoryBean factoryBean = new PropertiesFactoryBean();
factoryBean.setLocation(new ClassPathResource(QUARTZ_PROPERTIES_PATH));
try {
factoryBean.afterPropertiesSet();
return factoryBean.getObject();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
各文件内容:QuartzScheduler.java
package com.infosky.batch.quartz;
import static org.quartz.CronScheduleBuilder.cronSchedule;
import javax.annotation.PostConstruct;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.stereotype.Component;
/**
* 定时任务调度器
*/
@Component
public class QuartzScheduler {
@SuppressWarnings("SpringJavaAutowiringInspection")
@Autowired
private SchedulerFactoryBean schedulerFactoryBean;
@PostConstruct
public void init() throws SchedulerException {
scheduleJobs();
}
public void scheduleJobs() throws SchedulerException {
System.out.println("=======任务初始化========");
Scheduler scheduler = schedulerFactoryBean.getScheduler();
// 需要传递数据,就是使用JobDataMa
// JobDataMap jobDataMap = new JobDataMap();
// jobDataMap.put("jobArg", "world");
// CheckStatusTask.class 是需要执行定时任务的类名
JobDetail jobDetail = JobBuilder.newJob(CheckStatusTask.class)//.setJobData(jobDataMap)
// .setJobData(jobDataMap)
.withDescription("CheckStatusTask").withIdentity("job-CheckStatus", "demo-group").build();
// InsertEvaluateTask.class 是需要执行定时任务的类名
// JobDetail jobDetail2 = JobBuilder.newJob(InsertEvaluateTask.class)
// // .setJobData(jobDataMap)
// .withDescription("InsertEvaluateTask")
// .withIdentity("job-InsertEvaluate", "demo-group")
// .build();
Trigger trigger = TriggerBuilder.newTrigger().forJob(jobDetail).withSchedule(cronSchedule("*/1 * * * * ? "))
.build();
// Trigger trigger2 = TriggerBuilder.newTrigger()
// .forJob(jobDetail2)
// .withSchedule(cronSchedule("0 0/1 * * * ? "))
// .build();
try {
if (!scheduler.checkExists(JobKey.jobKey("job-CheckStatus", "demo-group"))) {
scheduler.scheduleJob(jobDetail, trigger);
}
// if(!scheduler.checkExists(JobKey.jobKey("job-InsertEvaluate","demo-group"))){
// scheduler.scheduleJob(jobDetail2,trigger2);
// }
scheduler.start();
System.out.println("=======任务初始化完成========");
} catch (SchedulerException e) {
e.printStackTrace();
}
}
}
●注意:利用数据库这种方式当程序意外终止或者需要修改定时任务时(比如删除一些定时任务),重新启动时有可能因为DB表数据与定时任务不整合可能出现启动异常异常,这时只需要删除Quartz对应的数据库表重新启动即可。
数据库对应表
qrtz_fired_triggers
qrtz_paused_trigger_grps
qrtz_scheduler_state
qrtz_locks
qrtz_simple_triggers
qrtz_cron_triggers
qrtz_simprop_triggers
qrtz_blob_triggers
qrtz_triggers
qrtz_job_details
qrtz_calendars
■zookeeper实现分布式锁方式
A.文件目录结构
B.各文件内容:pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.infosky.batch</groupId>
<artifactId>lpwmsbatch</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<name>lpwmsbatch</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.4.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.8</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.curator/curator-framework -->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>2.12.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.quartz-scheduler/quartz -->
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.2.3</version>
</dependency>
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz-jobs</artifactId>
<version>2.2.3</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
各文件内容:TaskService.java
package task;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Component
public class TaskService {
// 每分钟启动
@Scheduled(cron = "0 0/1 * * * ?")
public void oneMinuteJob(){
System.out.println("now time:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
}
}
各文件内容:SpringBootStartApplication.java
package com.infosky.batch;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication
@MapperScan("com.infosky.batch.dao")
@EnableScheduling
public class SpringBootStartApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootStartApplication.class, args);
}
}
各文件内容:ZookeeperUtils.java
package com.infosky.batch.utils;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.CreateMode;
public class ZookeeperUtils {
/**
* 创建节点。创建成功即获得执行权。
* @param strNote
* @throws Exception
*/
public static void createNote(String strNote) throws Exception {
// 获取连接
CuratorFramework curatorFramework = CuratorFrameworkFactory.builder().connectString("172.22.70.45:2181")
.sessionTimeoutMs(4000).retryPolicy(new ExponentialBackoffRetry(1000, 3)).namespace("curator").build();
curatorFramework.start();
try{
// 获取节点值
byte[] valNote = curatorFramework.getData().forPath("/taskLock");
// 节点存在时
if(valNote != null && valNote.length > 0){
// 获取节点值
String strVal = new String(valNote);
// 节点保存时间
long logVal = Long.parseLong(strVal);
// 当前时间
long logCurrent = DateUtils.getDateTime();
// 节点超过存活时间,删除节点
if(logCurrent - logVal > 1000*60*60){
curatorFramework.delete().forPath("/taskLock");
}
}
}catch(Exception e){}
// 创建节点
curatorFramework.create().withMode(CreateMode.PERSISTENT).forPath("/taskLock", String.valueOf(DateUtils.getDateTime()).getBytes());
}
}
各文件内容:测试代码:TTT.java
package com.infosky.batch.utils;
import java.util.Date;
public class TTT {
public static void main(String[] args) {
try {
ZookeeperUtils.createNote("");
System.out.println("$$$$$$$$$$$$$$$$$$$$$$$$$$$$抢到锁");
System.out.println(new Date());
} catch (Exception e) {
System.out.println("############################未抢到锁");
}
}
}
各文件内容:DateUtils.java
package com.infosky.batch.utils;
public class DateUtils {
public static final String JAVA_DATETIME_FORMATTER_24 = "yyyy-MM-dd HH:mm:ss";
/**
* 获取当前时间
* @return
*/
public static long getDateTime(){
return System.currentTimeMillis();
}
}
更多推荐
所有评论(0)