我目前正在处理在Spring Web应用程序幕后运行的计划任务。该任务使用cron调度程序在每晚午夜执行,并清理我的门户网站未使用的应用程序(我的网站允许用户创建一个应用程序来填写,如果他们不在30天内访问该表单,我的后台任务将从我们的数据库中删除它,并通知用户如果需要通过电子邮件创建新表单)。在我的测试环境中,一切都很好,我准备转向质量保证。
但是,我的下一个环境使用两个负载平衡的服务器来处理请求。这是一个问题,因为cron调度程序和我的轮询任务在两台服务器上同时运行。虽然对DB的读/写不是问题,但问题在于将通知电子邮件发送给应用程序用户。没有任何轮询锁定,可以生成和发送两封电子邮件,我想避免这种情况。通常,我们将使用SQL存储过程并在数据库中有一个字段用于锁定,然后在调用轮询代码时设置/释放,因此只会执行一个轮询实例。但是,根据我的新轮询任务,我们没有任何可用字段,因此我正在尝试使用SPRING解决方案。我在网上找到了这个资源:
http://www.springframework.net/doc-latest/reference/html/threading.html
我正在考虑将其用作
Semaphore _pollingLock = new Semaphore(1);
_pollingLock.aquire();
try {
//run my polling task
}
finally {
//release lock
}
但是,我不确定这是否只是确保第二个实例执行之后,或者它会跳过第二个实例并且永远不会执行。或者,这个解决方案是否合适,并且有更好的解决方案。再次,我使用的是Spring java框架,因此任何存在的解决方案都是我最好的选择。
答案 0 :(得分:0)
过去我们处理此类问题的两种方式都是从指定我们的一个群集服务器开始,作为负责特定任务的一个(例如,发送电子邮件或运行作业)。
在一个解决方案中,我们在所有群集服务器上设置JVM参数,以标识应在其上运行进程的一台服务器的服务器名称。例如-DemailSendServer = clusterMember1
在另一个解决方案中,我们仅在此指定服务器的启动时提供了一个JVM参数。例如-DsendEmailFromMe = true
在这两种情况下,您都可以在流程中添加一小段代码,以根据启动参数的值或存在来对其进行门控。
我发现第二个选项更易于使用,因为参数的存在足以允许进程运行。在第一个解决方案中,您必须将当前服务器名称与参数值进行比较。
我们对Spring Batch没有做太多工作,但我认为有一种方法可以配置批处理以在集群内的单个服务器上运行作业。