[eggjs/egg]egg集群部署下,定时器如何防止重复执行?

2025-10-27 162 views
1

看了官方案例 扩展定时任务类型

module.exports = agent => {
  class ClusterStrategy extends agent.ScheduleStrategy {
    start() {
      // 订阅其他的分布式调度服务发送的消息,收到消息后让一个进程执行定时任务
      // 用户在定时任务的 schedule 配置中来配置分布式调度的场景(scene)
      agent.mq.subscribe(this.schedule.scene, () => this.sendOne());
    }
  }
  agent.schedule.use('cluster', ClusterStrategy);
};

这个在egg-redis里面需要怎么用呢,能否提供一个简单的demo,找了很多的文档,都没有看到怎么去使用

回答

4

我也查看了issues里面有很多这样的问题,但是存这样看,理解还是有偏差。希望能提供一个简单的demo,egg-redis 版本的,因为这个是最常用的。

8
module.exports = agent => {
  agent.messenger.on('egg-ready', () => {
    agent.redis.subscribe('task');
  });

  class RedisStrategy extends agent.ScheduleStrategy {
    start() {
      // 订阅其他的分布式调度服务发送的消息,收到消息后让一个进程执行定时任务
      agent.redis.on('message', (channel, message) => {
        if (channel === 'task') {
          this.sendOne(message);
        }
      });
    }
  }
  agent.schedule.use('cluster', RedisStrategy);
};

如果这样写的话,集群下多个实例都订阅了task,那么他是如何保证集群下有且只有一个实例执行定时任务呢

0

@atian25

9

如果是 redis 的话,不应该用订阅,而是用锁机制,触发后,每个 worker 去抢一个锁,抢到的才执行。

集群任务肯定需要一个调度者,要不就是每个 worker 启动时都注册到一个三方平台,由它来调度通知到哪个 worker。 要不就是没有 leader 而是每个 worker 来抢分布式锁。

@thonatos 写个 demo or 插件?

8

如果是 redis 的话,不应该用订阅,而是用锁机制,触发后,每个 worker 去抢一个锁,抢到的才执行。

@thonatos 写个 demo or 插件?

我也是这样想,所以我找的很多例子都是我后面贴的代码这样写,我就觉得很奇怪。我是前端转的,所以对这块不是很熟练。如果官方能集成一个插件就好了,因为这个问题,我在issue里面看到很多次,很多人都有这样的疑惑

7

如果可以提供一个demo也可以,

0

这不是一个框架能实现的东西,是个系统工程,方法思路提供给你就是用锁、调度器,需要自己去实现了。

8

这不是一个框架能实现的东西,是个系统工程,方法思路提供给你就是用锁、调度器,需要自己去实现了。

我能理解,我是说这个问题还是很常见的,如果懂的人能出一个egg插件对我这种小白最好不过了。分布式锁是一种方案,目前我正在查找相应的demo

7

分布式锁倒是可以通过插件实现,欢迎实现之后开源出来贡献给大家用

8

目前利用bull的定时器实现集群定时器

1

这个问题可以关了

3

bull 可以直接使用,无需额外配置,我用的社区版本egg-bus

1

这种集群部署的服务最好是 把定时任务的服务抽离出来,单独部署 ,省事省心

2

我以k8s集群为例。在不引入额外的开源软件解决方案的前提下, 我当初构想的时候有两种方案: 1,使用一个集中的linux容器,利用其crontab能力,以http方式去触发Node接口服务(这是对于web server的情形而言的) 2,通过环境变量的形式,控制定时任务是否执行。然后部署两个工作负载(这两个负载都是同一套代码镜像,不用维护多套),其中一个工作负载是无环境变量的,可以多实例。一个工作负载是单实例,通过环境变量的方式启用其定时服务。

对于我,由于实际中涉及到多语言的服务,不仅仅要执行node的定时服务,所以我是采用通用的方案1 crontab

6

分布式锁倒是可以通过插件实现,欢迎实现之后开源出来贡献给大家用

egg-cluster-schedule 整了一个插件

8

请问这个具体是怎么用的,能提供下方法吗

4

egg-rds-lock 可以用这个插件