使用spring cloud[Dalston.SR1]版本开发定时job时,发现job执行了两次;
下面日志里发现一个job被一个任务调度池(task-scheduler)里的两个worker(task-scheduler-1 和 task-scheduler-2)执行,很奇怪;2018-02-23 14:28:30.001 [task-scheduler-2] INFO c.k.micro.cfca.scheduled.ContractSealApplyJob - ==回调job==开始==2018-02-23 14:28:30.002 [task-scheduler-2] INFO c.k.micro.cfca.scheduled.ContractSealApplyJob - ==回调job==结束==2018-02-23 14:28:30.003 [task-scheduler-1] INFO c.k.micro.cfca.scheduled.ContractSealApplyJob - ==回调job==开始==2018-02-23 14:28:30.003 [task-scheduler-1] INFO c.k.micro.cfca.scheduled.ContractSealApplyJob - ==回调job==结束==
在构造方法里加入log,确认了类只被加载了一次;
示例代码:
@RefreshScope@Component@EnableSchedulingpublic class ContractSealApplyJob{ @Value("${value1}") private String value1; /** * 进行回调job */ @Scheduled(cron = "${0/30 * * * * *}")//每30秒 public void doCallBack(){ logger.info("==回调job==开始=="); .... logger.info("==回调job==结束=="); }}
发现是spring cloud config 里的注解@RefreshScope导致;正确用法是把配置项放到一个Config类里面;然后在Job里注入。 @RefreshScope注解的类,在运行时刷新后,会重新生成一个新的实例;不过在上述Job里并未被重新实例化(没有刷新),而是把Job放入池里两次。
/** * Convenience annotation to put a @Bean
definition in * {@link org.springframework.cloud.context.scope.refresh.RefreshScope refresh scope}. * Beans annotated this way can be refreshed at runtime and any components that are using * them will get a new instance on the next method call, fully initialized and injected * with all dependencies. * * @author Dave Syer * */@Target({ ElementType.TYPE, ElementType.METHOD })@Retention(RetentionPolicy.RUNTIME)@Scope("refresh")@Documentedpublic @interface RefreshScope { /** * @see Scope#proxyMode() */ ScopedProxyMode proxyMode() default ScopedProxyMode.TARGET_CLASS;}
@RefreshScope还有别的坑,详见: