内容简介:在我工作的公司,我们使用无论如何,有时在超高峰期间,Quartz表会遇到数据库锁定问题。所以我在想什么是Quartz替代品。以下项目前景看好:但是,让我们尝试一些轻松简单的方法,如何使用
在我工作的公司,我们使用 Quartz 进行作业调度。大部分时间Quartz都在为我们提供所需的一切:
- 通过cron表达式进行调度。
- 监控和启动已启动的工作......
无论如何,有时在超高峰期间,Quartz表会遇到数据库锁定问题。所以我在想什么是Quartz替代品。以下项目前景看好:
- Cron4J
- Apache Ignite(哦,是的!)
但是,让我们尝试一些轻松简单的方法,如何使用 Spring Scheduling 实现任务启动,以及使用 Hazelcast 数据网格实现集群编排?
Spring Scheduling和Hazelcast一起运行
任务目标:假设我想在两个微服务上每2秒启动一次特定任务,我想确保群集中始终只有一个任务在运行!
这是Hazelcast派上用场的时刻。我们将为它测试两种Hazelcast解决方案:
- ILock - Hazelcast分布式锁,用于访问关键部分。只允许一个线程位于关键部分。
- ISemaphore - 用于关键部分编排的集群范围计数信号量。允许多个线程位于关键部分。取决于设置。
在ILock和ISemaphore这两个分布式对象之间的重要区别在于ILock需要由请求锁定的同一线程释放。另一方面,ISemaphore可以通过完全另一个线程释放。
- ISemaphore - 如果你想异步解锁关键部分,那么ISemaphore就是你的方式。
- ILock - 访问需要同步应答的一些共享资源是ILock的一种方式。
演示
让我们有两个微服务在工作后每两秒启动一次:
<b>private</b> <b>void</b> doJob(<b>final</b> String microServiceName)抛出InterruptedException { System.out.println(microServiceName +“in critical section ...”); <b>for</b>(<b>int</b> i = 0; i <4; i ++){ Thread.sleep(1000); System.out.println(“在做什么”+ microServiceName); } }
用ILock演示
如上所述,我们希望确保只有线程处于关键部分:(ILock解决方案)
<b>public</b> <b>void</b> performJobWithLock(<b>final</b> String microServiceName) { <b>final</b> ILock lock = hazelcastConfiguration.getJobLock(); <b>if</b> (lock.tryLock()) { <b>try</b> { doJob(microServiceName); } <b>catch</b> (InterruptedException e) { e.printStackTrace(); } <b>finally</b> { lock.unlock(); } } } @Scheduled(fixedRate = 2000) <b>public</b> <b>void</b> performJob() { jobServices.performJobWithLock(<font>"service1"</font><font>); } </font>
请注意,在try / finally块之前获取锁定(tryLock方法)。我使用的tryLock方法在获取锁定方面更安全,因为跳过了try / finally块。但是当使用ILock.lock()方法时,您需要知道未授予锁定的可能性,然后ILock.unlock()方法引发IllegalStateException。
测试
- 打开两个终端窗口。
- git clone https://bitbucket.org/tomask79/spring-integration-hazelcast.git
- 在pom.xml的顶级目录中运行“mvn clean install”
- 第一个终端中的java -jar spring-microservice-service1 / target / service1-0.0.1-SNAPSHOT.war。
- java -jar spring-microservice-service2 / target / service2-0.0.1-SNAPSHOT.war在第二个终端。
- 在你启动两个微服务之后,输出将出现在两个窗口中,但绝不会同时出现!
第一个终端:
service1 in critical section... Doing something in service1 Doing something in service1 Doing something in service1 Doing something in service1
第二个终端:
service2 in critical section... Doing something in service2 Doing something in service2 Doing something in service2 Doing something in service2
使用ISemaphore进行演示
与ILock相同,但这次ISemaphore是从另一个线程异步释放的:
<b>public</b> <b>void</b> performJobWithSemaphore(<b>final</b> String microServiceName) { <b>final</b> ISemaphore semaphore = hazelcastConfiguration.getJobSemaphore(); <b>try</b> { semaphore.acquire(); Thread thread = <b>new</b> Thread() { <b>public</b> <b>void</b> run() { <b>try</b> { <b>try</b> { doJob(microServiceName); } <b>catch</b> (InterruptedException e) { e.printStackTrace(); } } <b>finally</b> { semaphore.release(); System.out.println(<font>"Thread released semaphore..."</font><font>+microServiceName); } } }; thread.start(); } <b>catch</b> (InterruptedException e) { e.printStackTrace(); } } </font>
不要忘记将ISemaphore permits 的数量设置为1.我们希望ISemaphore表现为ILock,但我们需要能够从另一个线程中释放临界区。
@Bean <b>public</b> ISemaphore getJobSemaphore() { ISemaphore semaphore = hazelcastInstance().getSemaphore(<font>"criticalJobSemaphore"</font><font>); semaphore.init(1); <b>return</b> semaphore; } </font>
测试
以与ILock相同的方式启动两个微服务。以下输出将在两个终端窗口中显示,但同样,永远不会同时出现!
第一个终端
Doing something in service1 Doing something in service1 Doing something in service1 Doing something in service1 Thread released semaphore...service1
第二终端
Doing something in service2 Doing something in service2 Doing something in service2 Doing something in service2 Thread released semaphore...service2
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- Kubernetes-项目中pod调度使用法则
- 比特币源码分析:任务调度器的使用
- 使用DataWorks来调度AnalyticDB任务 原 荐
- go任务调度4(etcd安装和基本使用)
- 两个非常有意思的适合桌面使用的 Linux task 调度器:BFS 和 MuqSS
- 理解golang调度之一 :操作系统调度
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。