Spring 启动Web服务/微服务和调度

Spring boot Webservice / Microservices and scheduling

我有一个公开 REST API 的 spring 引导应用程序,我还计划添加一个 spring 引导计划任务。

任务的目的是从 momgodb 数据存储中获取一些待处理的 'reservations' 并进行处理。

现在的问题是,当多个服务实例 运行 时,所有节点很可能会选择相同的 'reservation records'。

我正在为此查看 mongodb 锁,并正在检查 mongodb 的 updateAndModidy / 事务(在 4.x 中)。

也可以单独锁定 table 只有一条记录,我锁定记录并执行操作和解锁记录。但是这样一次只有一个节点会工作,如果解锁操作失败,也会产生清理锁的开销。

所以问题是关于多个服务实例 运行 和如上所述安排任务。如果有人能指出围绕该主题的最佳实践或解决方案,无论技术如何(spring 引导/mongodb 等),我将不胜感激。

根据您的部署,一个适用于我们的解决方案是使用 Hazelcast 创建一个包含来自同一应用程序的节点的集群,然后当任务 运行 时,所有节点检查它们是否是主节点只有主人 运行 才是任务。

您可以在 Spring 此处阅读有关 Hazelcast 的介绍:https://josdem.io/techtalk/spring/spring_boot_hazelcast_es/

我们使用的是带 Consul 的 Hazelcast,因此我们不必手动配置 ips/ports,使用以下命令:https://github.com/bitsofinfo/hazelcast-consul-discovery-spi

如果您没有很多(动态)节点,这是一个相对简单的解决方案,对我们来说效果很好(3 个节点,与 Jenkins 的 consul/fabio 协调零停机部署)

过去我们让 Quartz 调度协调所有节点,使用 Quartz 的公共 JDBC 数据源作为同步机制,但实现是错误的,时不时地我们会以 TABLE 我们必须手动解锁的锁,杀死一些节点。

干杯

编辑:

这就是我们的 class 之一的样子:

// Optionally autowired, in case we don't run in a cluster (development)
private final Optional<HazelcastInstance> hazelcast;

    @Scheduled(cron = "${refresh.cron}")
    public void scheduledRefresh() {
        // Run if we are not in a cluster or 
        // we are the first member of the cluster
        if (!hazelcast.isPresent() || 
   hazelcast.get().getCluster().getMembers().iterator().next().localMember()) {
    // Run restricted method
   }