본문 바로가기
카테고리 없음

bull queue 동시성(concurrency) 설정 이슈. - 설정한 값보다 훨씬 많은 job이 실행되는 이슈

by asj8000 2024. 6. 2.
반응형

nestjs/bull 를 쓰다, 동시성(concurrency) 옵션에 관련한 이슈를 발견하여 포스팅해본다.

nestjs/bull queue에서는 아래처럼 concurrency를 설정할 수 있다.

# nestjs
@Processor('test-queue')
export class testQueueConsumer {
  @Process({
    name: 'someJob',
    concurrency: 5,
  })
  async processSomeJob(
  ...

 

 

이슈사항

nestjs/bull queue를 사용하다가

concurrency를 설정하지 않았음에도 불구하고 여러 job이 동시에 작동되며,

concurrency를 설정할 경우 설정값보다 훨씬 더 많은 개수의 job이 동시에 작동되는 현상을 확인했다.

 

*nestjs/bull을 쓰다 발견했을뿐, bull 라이브러리 자체의 이슈이다.

 

결론먼저

동일한 큐 안 대해 여러 Process를 정의하면,  소비자의 동시성 설정이 합산된다.

그 합산한 갯수만큼 실제 동시성이 결정되게 된다.

 

상세 이슈 분석

Bull 라이브러리에서의 현재 설계 구조에서는 동시성이 process 아닌 processor 수준에서 관리된다.

그래서, 동일한 큐에 대해 여러 process를 호출할떄마다, 각 호출의 동시성 설정이 processor에 합산된다.

const queue = new Queue('my-queue');

queue.process('task1', 5, async (job) => {
  // task1 처리
});

queue.process('task2', 5, async (job) => {
  // task2 처리
});

예를들어 위와 같이 소비자를 정의한 경우, task1과 task2의 동시성 설정이 5이므로,

이 큐의 총 동시성이 10이 된다.

task1을 작동하던 task2를 작동하던, 동시에 10개가 작동하게 된다.

 

 

관련 git issue

Can't define a concurrency with a 0 value using the @Processor decorator #258

Multiple named consumers are sharing concurrency settings #867

Processors with multiple processes inconsistently process jobs #1813

 

 

 

*nestjs/bull 의 공식 문서에서 또한 경고하고 있는 내용이다.

 

 

해결 방법

 

1.  여러 process중 하나에만 concurrency를 1로, 나머지는 concurrency를 0으로. 설정

이렇게 될 경우 여러 process가 추가된다 하더라도 동시성 1을 유지할 수 있다.

@Process({ name: NAMED_JOB_1, concurrency: 1 })
async updateJob1(job: Job<any>) { }

@Process({ name: NAMED_JOB_2, concurrency: 0 })
async updateJob2(job: Job<any>) { }

Can't define a concurrency with a 0 value using the @Processor decorator #258

 


2. 여러 작업들에 대해 한 Process로 처리하기.

이럴경우 무조건 한 process만 정의하기에 동시성을 유지할 수 있다.

@Processor('SOCIAL_ENTITY_JOBS')
export class Processor {
  constructor() {}
  
  @Process({ name: '*', concurrency: 1 })
  async processJob(job: Job<unknown>) {
    switch (job.name) {
      case "create_post":
        return this.create_post(job);
      case "update_post":
        return this.update_post(job);
    }
  }

  async create_post(job: Job<unknown>) {
    // handling logic is here
  }

  async update_post(job: Job<unknown>) {
    // handling logic is here
  }
}

 

Global concurrency limit #1853

 

 

 

다만, 여전히 process별 동시성 설정은 불가능하다.

bull을 사용할 때 특정 process만의 동시성을 관리하고 싶으면 해당 process를 처리하는 큐 자체를 분리하던가 해야한다.

 

반응형

댓글