Nestjs项目实战 任务调度与定时任务实现

在Nestjs项目中实现任务调度和定时任务时,遇到了几个问题想请教大家:

  1. 如何正确使用@nestjs/schedule模块配置定时任务?我的任务有时无法按预期时间触发
  2. 动态创建/取消定时任务的推荐做法是什么?目前尝试用SchedulerRegistry修改cron表达式但不起作用
  3. 集群环境下部署时,定时任务会被多个实例重复执行,有什么解决方案?
  4. 长时间运行的定时任务阻塞主线程,是否应该改用Queue或单独微服务处理?
  5. 有没有成熟的错误处理机制?现在任务报错会导致整个应用崩溃
3 回复

在NestJS中实现任务调度和定时任务,可以使用node-schedulecron模块。以下是基本步骤:

  1. 安装依赖

    npm install node-schedule
    
  2. 创建任务服务: 创建一个服务来管理定时任务,例如tasks.service.ts

    import { Injectable } from '[@nestjs](/user/nestjs)/common';
    import schedule from 'node-schedule';
    
    [@Injectable](/user/Injectable)()
    export class TasksService {
      startTask() {
        schedule.scheduleJob('*/5 * * * *', () => {
          console.log('每5分钟执行一次');
        });
      }
    }
    
  3. 在模块中注入服务: 在app.module.ts中引入并注入该服务。

    import { Module } from '[@nestjs](/user/nestjs)/common';
    import { AppController } from './app.controller';
    import { AppService } from './app.service';
    import { TasksService } from './tasks/tasks.service';
    
    [@Module](/user/Module)({
      imports: [],
      controllers: [AppController],
      providers: [AppService, TasksService],
    })
    export class AppModule {}
    
  4. 启动任务: 在main.ts中调用任务服务的方法。

    async function bootstrap() {
      const app = await NestFactory.create(AppModule);
      const tasksService = app.get(TasksService);
      tasksService.startTask();
      await app.listen(3000);
    }
    bootstrap();
    

这样就实现了简单的定时任务调度。可根据需求调整调度规则。


在NestJS中实现任务调度和定时任务,可以使用@nestjs/schedule模块。首先安装依赖:

npm install @nestjs/schedule --save

然后启用定时任务模块,在app.module.ts里配置:

import { Module } from '@nestjs/common';
import { ScheduleModule } from '@nestjs/schedule';

@Module({
  imports: [
    ScheduleModule.forRoot(),
  ],
})
export class AppModule {}

接着创建一个定时任务服务,比如task.service.ts

import { Injectable } from '@nestjs/common';
import { SchedulerRegistry } from '@nestjs/schedule';

@Injectable()
export class TaskService {
  constructor(private schedulerRegistry: SchedulerRegistry) {}

  addCronJob(name: string, cronTime: string, callback: Function) {
    const job = new CronJob(cronTime, callback);
    this.schedulerRegistry.addCronJob(name, job);
    job.start();
  }

  stopCronJob(name: string) {
    const job = this.schedulerRegistry.getCronJob(name);
    if (job) {
      job.stop();
      this.schedulerRegistry.deleteCronJob(name);
    }
  }
}

通过注入TaskService即可灵活地添加或停止定时任务,比如每5秒执行一次任务:

this.taskService.addCronJob('testJob', '* * * * *', () => console.log('任务执行'));

记得处理好任务异常,避免程序崩溃。

NestJS 任务调度与定时任务实现

在NestJS中实现任务调度和定时任务主要有以下几种方式:

1. 使用@nestjs/schedule模块

这是NestJS官方提供的定时任务解决方案,基于node-cron和node-schedule。

安装依赖

npm install --save [@nestjs](/user/nestjs)/schedule

基本使用

import { Module } from '[@nestjs](/user/nestjs)/common';
import { ScheduleModule } from '[@nestjs](/user/nestjs)/schedule';

@Module({
  imports: [
    ScheduleModule.forRoot()
  ],
})
export class AppModule {}

三种类型的定时任务

  1. Cron表达式任务
import { Injectable, Logger } from '[@nestjs](/user/nestjs)/common';
import { Cron } from '[@nestjs](/user/nestjs)/schedule';

@Injectable()
export class TasksService {
  private readonly logger = new Logger(TasksService.name);

  @Cron('45 * * * * *') // 每分钟的第45秒执行
  handleCron() {
    this.logger.debug('每分钟第45秒执行的定时任务');
  }
}
  1. 间隔任务
import { Injectable, Logger } from '[@nestjs](/user/nestjs)/common';
import { Interval } from '[@nestjs](/user/nestjs)/schedule';

@Injectable()
export class TasksService {
  private readonly logger = new Logger(TasksService.name);

  @Interval(10000) // 每10秒执行一次
  handleInterval() {
    this.logger.debug('每10秒执行的定时任务');
  }
}
  1. 超时任务
import { Injectable, Logger } from '[@nestjs](/user/nestjs)/common';
import { Timeout } from '[@nestjs](/user/nestjs)/schedule';

@Injectable()
export class TasksService {
  private readonly logger = new Logger(TasksService.name);

  @Timeout(5000) // 应用启动5秒后执行一次
  handleTimeout() {
    this.logger.debug('应用启动5秒后执行的定时任务');
  }
}

2. 使用动态API

import { Injectable } from '[@nestjs](/user/nestjs)/common';
import { SchedulerRegistry } from '[@nestjs](/user/nestjs)/schedule';

@Injectable()
export class TasksService {
  constructor(private schedulerRegistry: SchedulerRegistry) {}

  addCronJob(name: string, seconds: string) {
    const job = new CronJob(`${seconds} * * * * *`, () => {
      console.log(`时间 ${seconds} 秒时执行的任务`);
    });

    this.schedulerRegistry.addCronJob(name, job);
    job.start();
  }

  deleteCronJob(name: string) {
    this.schedulerRegistry.deleteCronJob(name);
  }
}

3. 使用分布式任务调度(如Bull)

对于需要分布式和持久化的复杂任务调度,可以使用Bull模块:

import { Module } from '[@nestjs](/user/nestjs)/common';
import { BullModule } from '[@nestjs](/user/nestjs)/bull';

@Module({
  imports: [
    BullModule.forRoot({
      redis: {
        host: 'localhost',
        port: 6379,
      },
    }),
    BullModule.registerQueue({
      name: 'scheduledTasks',
    }),
  ],
})
export class AppModule {}

以上是NestJS中实现定时任务的主要方式,根据项目需求选择合适的方法即可。

回到顶部