1

我最近将我们几乎所有服务的实现都切换到了 Spring Cloud 功能,这自然也意味着所有预定的作业都已转换为供应商,例如从这个

@Scheduled(cron = "${retry.job.cron.time}")
@SchedulerLock(name = "retryProcess_scheduledTask", lockAtMostFor = "${retry.job.lock.atMost}", lockAtLeastFor = "${retry.job.lock.atLeast}")
public void retryUnprocessedItems() { ...}

对此

@PollableBean
public Supplier<List<Message<ProductValidatedEvent>>> retryUnprocessedItems() { ... }

正如您所看到的,这里唯一的障碍是实现某种分布式锁机制,以防止那些被PollableBean注释Suppliers的对象在所有服务实例上启动。

我曾考虑将计划的作业恢复到它们所在的位置并StreamBridge用来解决这个问题,但这听起来更像是一个黑客而不是一个解决方案。

另一种思路是将供应商转为Function接口类型,通过普通的带@Scheduled注解的方法调用,不过这个好像和Spring cloud的功能也不好设置。

有任何想法吗?

4

2 回答 2

1

这真的很有趣。我看到解决这个问题的两种方法。

  1. 最直接的就是在另一种方法上使用AOP
@PolllableBean
public Supplier<Void> retryUnprocessedItems(){ 
    return otherBean::doIt;
}

class OtherBean {
  @SchedulerLock(...)
  public void doIt() {
    ....
  }
}

请注意,该方法在不同的类上实现以允许 AOP 工作。此外,我必须将返回类型更改为,Void因为如果锁被锁定,我们不知道要返回什么。

  1. 另一种选择是在没有框架的情况下使用锁定
于 2022-01-17T18:22:12.270 回答
0

根据上面 Lukas 的回答,我已经能够更新我的代码,以便它使用 Spring AOP,我创建了一个ScheduledTask组件,它只有一个包含Supplier逻辑的方法,用@SchedulerLock注释标记,并返回稍后由供应商发出的值进入卡夫卡话题

@Autowired
ScheduledTask task;

@PollableBean
public Supplier<String> getScheduledJob() {
    return task::fire;
}

@Slf4j
@Component
class ScheduledTask {
    @SchedulerLock(name = "myJobLock", lockAtMostFor = "10s", lockAtLeastFor = "1s")
    public String fire() {
        log.info("Task was fired");
        return (String.valueOf(System.currentTimeMillis()));
    }
}

你可以在这里找到一个运行示例https://github.com/Mahm0ud/ShedlockWithSpringCloudFunction

于 2022-01-18T17:39:32.327 回答