Spring使用注释@Scheduled进行定期任务执行,在单个Tomcat下,是Ok的,一旦在集群环境下,就会执行多次的定时任务。
如果使用单个数据库,可能增加作任务状态表T。在每个Tomcat启动时,检查任务表T的执行状态,已执行则跳过,未执行则启动任务。在Tomcat关闭时,置任务状态表的执行状态为0。但是一旦发生Tomcat异常关闭,有可能发生任务状态表 的执行状态一直为 1 。
这属于分布式环境下的状态同步问题,解决办法就是找一个单点记录状态信息,如你描述中的使用DB进行单点状态记录,Zookeeper也可以作为单点记录状态。思路很简单:在任务执行前读取DB,看下当前任务是否已经在其他节点上执行,如果没有,那么在DB中将执行状态改为执行中,当执行完毕后将任务执行状态改为已经结束。为了防止Tomcat 宕机导致的DB中状态未及时更新,可以增加一个开始执行时间字段,如果过了一段时间后依旧未更新为执行结束,那么可以认为执行该任务的Tomcat出现了异常情况。另外,如果使用ZK来记录状态的话,可以使用一种类型为Ephamal的类型来记录状态。
给这个定时任务的执行方法前加上一个配置文件的参数判断,集群中的N个server分别判断各自应用下的properties文件中的状态是开还是关。建一个servlet或action,该链接可以通过指定参数来开启或关闭定时任务的开发。发布后,通过指定IP的server访问该应用的url,开启一个应用下的开关即可。开即执行,关即跳过。
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。