Skip to content

2. Backends and Brokers


1. Using RabbitMQ

1) Installation & Configuration

  • RabbitMQ는 기본 브로커이므로 사용하려는 브로커 인스턴스 URL 위치를 제외한 추가 종속성이나 초기 구성이 필요하지 않다.


broker_url = "amqp://myuser:mypassword@localhost:5672/myvhost"


2) Setting up RabbitMQ

  • Celery를 사용하려면 가상 호스트인 RabbitMQ 사용자를 만들고, 해당 사용자가 해당 가상 호스트에 액세스할 수 있도록 허용해야 한다.


sudo rabbitmqctl add_user myuser mypassword
sudo rabbitmqctl add_vhost myvhost
sudo rabbitmqctl set_user_tags myuser mytag
sudo rabbitmqctl set_permissions -p myvhost myuser ".*" ".*" ".*"


  • 위 코드의 myuser, mypasswordmyvhost를 적절하게 변경하여 사용하면 된다.


3) Installing RabbitMQ on macOS

  • macOS에 RabbitMQ를 설치하는 가장 쉬운 방법은 macOS 전용 패키지 관리 시스템인 Homebrew를 사용하는 것이다.


  • 먼저 Homebrew를 설치한다.


/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"


  • Homebrew가 설치되었으면 brew 명령을 사용하여 RabbitMQ를 설치한다.


brew intall rabbitmq


  • brew 명령을 통해 RabbitMQ를 설치한 경우 브로커를 시작 및 중지할 수 있도록 경로에 다음을 추가해야 한다.


PATH=$PATH:/usr/local/sbin


4) Configuring the system host name

  • 임의의 호스트 이름을 제공하는 DHCP 서버를 사용하는 경우 호스트 이름을 영구적으로 구성해야 한다.
  • 왜냐하면 RabbitMQ는 호스트 이름을 사용하여 노드와 통신하기 때문이다.
  • scutil 명령을 사용하여 호스트 이름을 영구적으로 설정한다.


sudo scutil --set HostName myhost.local


  • 그런 다음 해당 호스트 이름을 /etc/hosts에 추가하여 IP 주소로 다시 확인할 수 있다.


127.0.0.1       localhost myhost myhost.local


  • rabbitmq-server를 시작하면 rabbitmqctl에서 확인한 것처럼 노드가 rabbit@myhost가 되어야 한다.


sudo rabbitmqctl status
Status of node rabbit@myhost ...
[{running_applications,[{rabbit,"RabbitMQ","1.7.1"},
                    {mnesia,"MNESIA  CXC 138 12","4.4.12"},
                    {os_mon,"CPO  CXC 138 46","2.2.4"},
                    {sasl,"SASL  CXC 138 11","2.1.8"},
                    {stdlib,"ERTS  CXC 138 10","1.16.4"},
                    {kernel,"ERTS  CXC 138 10","2.13.4"}]},
{nodes,[rabbit@myhost]},
{running_nodes,[rabbit@myhost]}]
...done.


  • 위의 과정은 DHCP 서버가 IP 주소로 시작하는 호스트 이름을 제공하는 경우 특히 중요하다.
  • 예를 들어 23.10.112.31.comcast.net인 IP 주소가 있을 때 RabbitMQ는 rabbit@23이라는 잘못된 호스트 이름을 사용하려고 시도한다.


5) Starting/Stopping the RabbitMQ server

  • 다음과 같이 서버를 시작한다.


sudo rabbitmq-server


  • -detached 옵션을 추가하면 백그라운드에서 실행할 수 있다.


sudo rabbitmq-server -detached


  • RabbitMQ 서버를 중지할 때는 kill 명령을 사용하지 말고 rabbitmqctl 명령을 사용한다.


sudo rabbitmqctl stop


2. Using Redis

1) Installation & Configuration

  • Redis 지원을 위해 추가 종속성을 설치해야 한다.
  • celery[redis] 번들을 사용하여 Celery와 이러한 종속성을 한 번에 설치할 수 있다.


pip install "celery[redis]"


  • Redis 데이터베이스의 위치를 구성하면 된다.


app.conf.broker_url = "redis://localhost:6379/0"


  • 위의 URL의 형식은 다음과 같다.


redis://:password@hostname:port/db_number


  • 만약 Unix 소켓 연결을 사용해야 하는 경우 URL의 형식은 다음과 같다.


redis+socket:///path/to/redis.sock


  • URL에 virtual_host 매개변수를 추가하여 Unix 소켓을 사용할 때 다른 데이터베이스 번호를 지정할 수 있다.


redis+socket:///path/to/redis.sock?virtual_host=db_number


  • Redis Sentinel 목록에 직접 연결할 수도 있다.


app.conf.broker_url = "sentinel://localhost:26379;sentinel://localhost:26380;sentinel://localhost:26381"
app.conf.broker_transport_options = { "master_name": "cluster1" }


  • sentinel_kwargs를 사용하여 Sentinel 클라이언트에 추가 옵션을 전달할 수 있다.


app.conf.broker_transport_options = { "sentinel_kwargs": { "password": "password" } }


2) Visibility Timeout

  • 표시 시간 제한은 메시지가 다른 워커에게 다시 전달되기 전에 워커가 태스크를 승인할 때까지 기다리는 시간(초)을 정의한다.
  • 이 옵션은 broker_transport_options를 통해 설정된다.


app.conf.broker_transport_options = {"visibility_timeout": 3600}  # 1 hour.


  • 표시 시간 제한 내에 태스크가 확인되지 않으면 태스크는 다른 워커에게 다시 전달되어 실행된다.
  • 이로 인해 실행 시간이 표시 시간 제한을 초과하는 ETA/카운트다운/재시도 작업에 문제가 발생한다.
  • 실제로 그런 일이 발생하면 루프에서 다시 실행된다.
  • 따라서 사용하려는 가장 긴 ETA의 시간과 일치하도록 표시 시간 제한을 늘려야 한다.


app.conf.broker_transport_options = {"visibility_timeout": 43200}


3) Results

  • Redis에 태스크의 상태 및 반환 값도 저장하려면 다음 설정을 구성해야 한다.


app.conf.result_backend = "redis://localhost:6379/0"


  • Sentinel을 사용하는 경우, result_backend_transport_options를 사용하여 master_name을 지정해야 한다.


app.conf.result_backend_transport_options = {"master_name": "mymaster"}


4) Connection timeouts

  • Redis 결과 백엔드에 대한 연결 시간 초과를 구성하려면 result_backend_transport_options를 사용하여 retry_policy를 지정해야 한다.


app.conf.result_backend_transport_options = {
    "retry_policy": {
        "timeout": 5.0
    }
}


5) Key eviction

  • Redis는 메모리 관리를 위해 자동으로 데이터를 삭제할 수 있다.
  • 이런 경우 다음과 같이 특정 키에 접근하려는 경우 에러가 발생한다.


InconsistencyError: Probably the key ('_kombu.binding.celery') has been
removed from the Redis database.


  • 위의 문제를 해결하려면 구성 파일 중 다음의 내용을 수정한다.


1] maxmemory

2] maxmemory-policy


References