본문 바로가기

Tech/Celery

Docker를 활용한 Celery Worker, beat 분리

Base

아래 구성은 API Server <==> Redis <==> Celery의 구조를 기반으로 한다.

 


문제

기존 사용하던 Celery Worker는 1개의 Queue를 통해 간단한 작업을 처리하고 있었다.

주기적인 간격으로 동작해야하는 기능이 필요했고, 그 기능을 구현하기 위해 Celery Beat를 사용했다.

Celery Worker에 Beat Task를 위한 1개의 큐를 더 추가했고, 2개의 큐를 통해 각각의(기존 , 주기적) 작업을 처리하려 했다.

아래 명령어를 entripoint.sh에 추가하고 Docker를 통해 실행 시켰다.

# entripoint.sh
#
# 해당 파일은 Docker Image를 생성할 때 추가하는 파일이다. 
#

celery -A worker worker --loglevel=INFO --concurrency=1 -Q common, beat
#docker compose

celery-worker:
    image: <celery Base Server Image> # Entripoint.sh가 포함된 Image
    container_name: celery-worker
    environment:
      필요에 의한 환경 변수
    volumes:
      필요에 의한 볼륨 바인딩
    networks:
      사용중인 Docker Compose Network
    logging:
      로깅 방식
    depends_on:
      현재 이 컨테이너보다 먼저 실행 시킬 컨테이너 선언 
      # 다만, 완벽한 실행이 끝난 후가 아닌, 컨테이너 Start 그자체 그 뿐.
      # 만약 앞서 다른 컨테이너가 먼저 구동이 완전히 끝난 후 실행이 되야 한다면?
      # wait for it 같은 것을 찾아봐라.
    restart: always

이후 celery-worker 컨테이너를 구동했더니 Celery Worker가 정상적으로 동작하지 않았다.

 


해결

Celerey Worker를 분리하자

문제에 사용하던 Celery는 한개의 컨테이너 안에서 기존작업, 주기적 작업을 수행하는 Queue를 동시에 실행시켰다.

이렇게 실행하게 되면, 각 작업에 대한 오류가 발생했을 경우, 분리된 환경보다 관리하기 힘들다는점.

추가로, 한개의 작업에 대해 오류가 발생해도, 두개의 Worker가 Restart되야 한다는 점이 있었다.

원래 사용하던 방식(entripoint.sh)을 활용을 하기에는 Worker의 개수가 늘어날 때마다 증가해야하는 불편함이 존재하여,

Docker compose 내 Command 옵션을 활용하기로 했다.

 

결론적으로, 아래와같이 분리하였다.

  1. 기존작업을 하는 Worker
  2. Beat작업을 하는 Worker
  3. Beat Task를 발생시키는 Server

분리한 코드는 다음과 같다.

#docker compose

celery-common-worker:
    image: <celery Base Server Image>
    container_name: celery-common-worker
    environment:
      필요에 의한 환경 변수
    volumes:
      필요에 의한 볼륨 바인딩
    networks:
      사용중인 Docker Compose Network
    command: celery -A worker worker --loglevel=INFO --concurrency=1 -Q common
    logging:
      로깅 방식
    depends_on:
      현재 이 컨테이너보다 먼저 실행 시킬 컨테이너 선언 
    restart: always


celery-beat-worker:
    image: <celery Base Server Image>
    container_name: celery-beat-worker
    environment:
      필요에 의한 환경 변수
    volumes:
      필요에 의한 볼륨 바인딩
    networks:
      사용중인 Docker Compose Network
    command: celery -A worker worker --loglevel=INFO --concurrency=1 -Q beat
    logging:
      로깅 방식
    depends_on:
      현재 이 컨테이너보다 먼저 실행 시킬 컨테이너 선언 
    restart: always


celery-beat:
    image: <celery Base Server Image>
    container_name: celery-beat
    environment:
      필요에 의한 환경 변수
    volumes:
      필요에 의한 볼륨 바인딩
    networks:
      사용중인 Docker Compose Network
    command: celery -A worker beat -s ./task/schedule_beat_log/beat_log
    logging:
      로깅 방식
    depends_on:
      현재 이 컨테이너보다 먼저 실행 시킬 컨테이너 선언 
    restart: always
반응형

'Tech > Celery' 카테고리의 다른 글

[Celery]Pytest로 Celery Task 테스트 코드 작성하기  (0) 2021.12.21