java - Spring boot Web服务/微服务和调度

标签 java spring mongodb spring-boot scheduling

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

任务的目的是从 momgodb 数据存储中获取一些待处理的“预订”并进行处理。

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

我正在查看 mongodb 锁并检查 mongodb 的 updateAndModidy/transactions (in 4.x)。

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

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

最佳答案

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

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

我们使用的是 Hazelcast 和 Consul,所以我们不必手动配置 ips/端口,使用: 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
   }

关于java - Spring boot Web服务/微服务和调度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61068344/

相关文章:

Java - SimpleDateFormat 格式化程序以毫秒为单位返回纪元时间

java - 如何将对象从 primefaces 上的树传递到 View

java - 为什么企业要同时使用Struts 1和Spring

javascript - MongoDB 计数未返回正确的数字

macos - Mongorestore - 打开的文件太多 - mac os x

java - 为什么这个 java 代码没有在 Eclipse IDE 上显示。公共(public)类型App必须在自己的文件中定义

java - 如何定义 @transactional 身份管理器?

java - Spring单例导致内存泄漏

java - 将 exchange() 与 Spring WebClient 一起使用时如何抛出 WebClientResponseException

node.js - 如何处理 MongoDB 的断开连接错误