【问题标题】:Spring boot Webservice / Microservices and schedulingSpring boot Webservice / 微服务和调度
【发布时间】:2020-04-06 20:23:06
【问题描述】:

我有一个公开 REST API 的 Spring Boot 应用程序,并且还计划添加一个 Spring Boot 计划任务。

task 的目的是从 momgodb 数据存储中获取一些待处理的“保留”并进行处理。

现在的问题是,当多个服务实例运行时,所有节点很可能会获取相同的“预订记录”。

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

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

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

【问题讨论】:

标签: java spring mongodb spring-boot scheduling


【解决方案1】:

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

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

我们使用的是带有 Consul 的 Hazelcast,因此我们不必手动配置 ips/端口,使用:https://github.com/bitsofinfo/hazelcast-consul-discovery-spi

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

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

干杯

编辑:

这是我们班级的样子:

// 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
   }

【讨论】:

猜你喜欢
  • 2018-04-11
  • 2019-02-20
  • 2020-03-11
  • 2022-01-08
  • 2020-09-27
  • 2020-12-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多