■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();
}
}