在NestJS中如何配置与使用队列

4 阅读2分钟

参考文档 docs.nestjs.cn/techniques/…

一、安装依赖

npm install --save @nestjs/bullmq bullmq

二、配置队列

1. 修改app.module.ts

import { BullModule } from '@nestjs/bullmq';

@Module({
    imports: [
        // 全局变量配置
        ConfigModule.forRoot({
            envFilePath: [`.env.${process.env.NODE_ENV}`, '.env'],
            isGlobal: true,
        }),
        BullModule.forRoot({
            prefix: 'XXX', // Redis前缀
            connection: {
                host: process.env.REDIS_HOST, // IP
                port: parseInt(process.env.REDIS_PORT), // 端口
                password: process.env.REDIS_PASSWORD,  // Redis密码
            },
        })
    ],
    controllers: [AppController],
    providers: [AppService], // 全局服务
})
export class AppModule {}

2. 注册队列

有两种方式来注册队列

  1. 创建一个队列模块,来管理队列和注册队列
  2. 在需要使用队列的模块中直接注册

方式一:创建队列模块注册队列

// queue/queue.module.ts

import { Module } from '@nestjs/common';
import { BullModule } from '@nestjs/bullmq';

@Module({
    imports: [
        // 注册一个video队列
        BullModule.registerQueue({
            name: 'video', // 队列名称
        }),
        // 如果需要多个队列也可以注册多个
        BullModule.registerQueue({
            name: 'email',
        }),
    ],
    exports: [BullModule],
})
export class QueueModule {}

方式二:在对应的业务模块中注册队列

// video/video.module.ts

import { Module } from '@nestjs/common';
import { BullModule } from '@nestjs/bullmq';

@Module({
    imports: [
        TypeOrmModule.forFeature([Video]), // 引入Video实体类
        // 注册一个video队列
        BullModule.registerQueue({
            name: 'video', // 队列名称
        }),
    ],
    controllers: [VideoController],
    providers: [VideoService],
})
export class VideoModule {}

三、使用队列

在队列中有两个概念: 生产者(向队列添加任务) 和 消费者(处理队列中的任务)

1. 向队列添加任务生产者

1.1 引入队列模块在业务模块中注册了该队列则不需要引入

// video/video.module.ts

import { QueueModule } from '../queue/queue.module';

@Module({
    imports: [
        TypeOrmModule.forFeature([Video]), // 引入Video实体类
        QueueModule, // 引入队列模块
    ],
    controllers: [VideoController],
    providers: [VideoService],
})
export class VideoModule {}

1.2 将任务添加到队列中

// video.service.ts
import { Queue } from 'bullmq';
import { InjectQueue } from '@nestjs/bullmq';

@Injectable()
export class VideoService {
    constructor(
        // 注入 videoQureue
        @InjectQueue('video') private videoQueue: Queue,
    ) {}

    // 上传视频链接
    async uploadVideo(data) {
        // 添加到video队列中
        await this.videoQueue.add('video', data);
    }

}

2. 处理队列中的任务消费者

2.1 创建消费者

// video.processor.ts

import { Processor, WorkerHost } from '@nestjs/bullmq';
import { Job } from 'bullmq';
import { Injectable } from '@nestjs/common';

@Processor('video', {
    concurrency: 3, // 并发处理,一次处理多个任务
})
@Injectable()
export class VideoProcessor extends WorkerHost {
    async process(job: Job<{ videoList: string }>) {
        console.log('处理Video队列任务', job.data);
        await new Promise((resolve) => setTimeout(resolve, 5000));
        console.log('处理Video队列完成');
    }
}

2.2 注入消费者

// video.module.ts

import { Module } from '@nestjs/common';
import { VideoService } from './video.service';
import { VideoController } from './video.controller';
import { Video } from './video.entity';
import { TypeOrmModule } from '@nestjs/typeorm';
import { VideoProcessor } from './video.processor';
import { QueueModule } from '../queue/queue.module';

@Module({
    imports: [
        TypeOrmModule.forFeature([Video]), // 引入Video实体类
        QueueModule, // 引入队列模块
    ],
    controllers: [VideoController],
    providers: [
        VideoService,
        // 注入消费者
        VideoProcessor
    ],
})
export class VideoModule {}