如何每晚在 JEE 集群上 运行 方法
How to run method every night on JEE Cluster
我在集群环境中的 Glassfish 3.1.2 上有一个 Java EE 应用程序 运行ning。
我想每天执行一次特定方法(即从数据库中删除一些条目)。
我创建了一个计时器:
@Singleton
public class TimerService {
@Schedule(second = "0", minute = "0", hour = "0", persistent=false)
public void runEveryDay() {
LOG.info("### runEveryDay");
}
当我查看日志时,该方法在两个集群节点上执行。我担心同时在两个节点上执行该方法时,我可能 运行 由于数据过时而出现问题。
有没有办法只在一个节点上执行该方法?或者我能以某种方式同步这些方法吗?
您可以通过使用预加载的数据库行作为事务锁来防止并发执行。
像这样写一个 JobLockService:
@Stateless
public class JobLockService {
@Resource
private DataSource serializableDS;
@TransactionAttribute(REQUIRES_NEW)
public boolean jobLockAcquired() {
// select jobLock record for update when flag = 0 and set flag
return true if record selected otherwise false
}
@TransactionAttribute(REQUIRES_NEW)
public void releaseJobLock() {
// reset jobLock record flag back to 0
}
}
然后提供你的单例:
@Singleton
public class TimerService {
@EJB
private JobLockService jobLockService;
@Schedule(second = "0", minute = "0", hour = "0", persistent=false)
public void runEveryDay() {
if (jobLockService.jobLockAcquired()) {
try {
LOG.info("### runEveryDay");
} finally {
jobLockService.releaseJobLock();
}
} else {
log.info("Job already running elsewhere");
}
}
在您的服务器中配置一个特殊的数据源,并将其事务隔离级别设置为 TRANSACTION_SERIALIZABLE 以防止并发问题。 (你通常不会使用这个设置,因为它的高负载并发性能很糟糕)
在 JobLockService 方法上使用 REQUIRES_NEW 事务将防止阻塞问题。
将您的计时器设置为持久性。然后它应该只在集群中的一个服务器节点上执行。
我在集群环境中的 Glassfish 3.1.2 上有一个 Java EE 应用程序 运行ning。
我想每天执行一次特定方法(即从数据库中删除一些条目)。
我创建了一个计时器:
@Singleton
public class TimerService {
@Schedule(second = "0", minute = "0", hour = "0", persistent=false)
public void runEveryDay() {
LOG.info("### runEveryDay");
}
当我查看日志时,该方法在两个集群节点上执行。我担心同时在两个节点上执行该方法时,我可能 运行 由于数据过时而出现问题。
有没有办法只在一个节点上执行该方法?或者我能以某种方式同步这些方法吗?
您可以通过使用预加载的数据库行作为事务锁来防止并发执行。
像这样写一个 JobLockService:
@Stateless
public class JobLockService {
@Resource
private DataSource serializableDS;
@TransactionAttribute(REQUIRES_NEW)
public boolean jobLockAcquired() {
// select jobLock record for update when flag = 0 and set flag
return true if record selected otherwise false
}
@TransactionAttribute(REQUIRES_NEW)
public void releaseJobLock() {
// reset jobLock record flag back to 0
}
}
然后提供你的单例:
@Singleton
public class TimerService {
@EJB
private JobLockService jobLockService;
@Schedule(second = "0", minute = "0", hour = "0", persistent=false)
public void runEveryDay() {
if (jobLockService.jobLockAcquired()) {
try {
LOG.info("### runEveryDay");
} finally {
jobLockService.releaseJobLock();
}
} else {
log.info("Job already running elsewhere");
}
}
在您的服务器中配置一个特殊的数据源,并将其事务隔离级别设置为 TRANSACTION_SERIALIZABLE 以防止并发问题。 (你通常不会使用这个设置,因为它的高负载并发性能很糟糕)
在 JobLockService 方法上使用 REQUIRES_NEW 事务将防止阻塞问题。
将您的计时器设置为持久性。然后它应该只在集群中的一个服务器节点上执行。