使用 Docker 时将 Celery 连接到 Redis 时出错

Error connecting Celery to Redis when using Docker

我已经使用 docker-compose 创建了一个包含 redis 和 celery 的 docker 实例。这将成功构建,但是,在我的 python 脚本中,当我尝试向我的队列添加内容时,出现以下错误:

Error 8 connecting to redis:6379. nodename nor servname provided, or not known.

我已经尝试更改我的 celeryconfig 文件地址,并尝试了这里建议的解决方案:https://github.com/mozilla-services/cliquet/issues/664 但我无法修复它。

有没有其他人遇到过这样的问题?

** example.py 的一部分 **

app = Celery('server', broker='redis://redis:6379/0')
app.config_from_object(celeryconfig)

@app.task(trail=True)
def count_words_at_url(url):
    time.sleep(50)
    resp = requests.get(url)
    return len(resp.text.split())

celeryconfig.py

result_backend = 'redis://redis:6379/0'
broker_url = 'redis://redis:6379/0'
worker_prefetch_multiplier = 1
worker_concurrency  =1

Dockerfile.celery

FROM python:3.6-alpine
WORKDIR /usr/src/app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ulimit -n 1024
CMD celery -A celeryExample worker --concurrency=1 --loglevel=info

docker-compose.yml

version: '3'

services:
  redis:
    image: redis
    ports:
      - 6379:6379
  celery: 
    build: 
        context: .
        dockerfile: Dockerfile.celery
    links: 
      - redis:redis
    depends_on:
      - redis
    volumes: 
        - .:/usr/src/app    

有了公认的答案(仍然需要将代理和后端拆分为单独的队列),我已经设法让一切正常工作,并进行了以下更改:

example.py:

broker_url = os.environ.get('broker_url', 'redis://localhost:6379'),
result_backend = os.environ.get('result_backend', 'redis://localhost:6379')

app = Celery('server', broker = broker_url,
                       backend = result_backend)
app.config_from_object(celeryconfig)

@app.task(trail=True)
def count_words_at_url(url):
    time.sleep(50)
    resp = requests.get(url)
    return len(resp.text.split())

Dockerfile.celery

FROM python:3.6-alpine
ENV CELERY_BROKER_URL redis://redis:6379/0
ENV CELERY_RESULT_BACKEND redis://redis:6379/0
ENV C_FORCE_ROOT true
WORKDIR /usr/src/app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD celery -A celeryExample worker --concurrency=1 --loglevel=info 

celeryconfig.py

worker_prefetch_multiplier = 1
worker_concurrency  =1

我认为问题在于您的客户端(尝试向您的 Celery 集群发送某些任务的应用程序)正在使用与您的 Celery worker 运行ning 相同的 celeryconfig 模块 运行ning =52=] 使用。

为什么这是个问题? - 因为 Docker 基础架构之外的所有内容都无法解析 redis。当然,如果您的客户端应用程序(生产者)运行s 在上面粘贴的 docker-compose 脚本中指定的任何 docker 容器上,它会起作用,但是如果您尝试 运行 以主机为例,它会失败。

为了让它工作,你需要获取容器的 IP 运行ning redis,并使用使用此 IP 地址的修改后的 celeryconfig。

您甚至可以省略我上面提到的步骤,只需在主机上的代理和 result_backend URL 中使用 localhost:6379 即可。我还建议您为这两个使用不同的 Redis 数据库(假设您使用 6 作为代理,使用 8 作为 result_backend)。

在您的 example.py 中,如果您将 redis://redis:6379/0 替换为 redis://localhost:6379/0,它应该可以工作。

总结一下:

  • 在您的 Docker 基础设施 中 运行 的所有 Celery worker 应该具有 redis://redis:6379/1 的 celeryconfig(对于例如)作为代理 URL,redis://redis:6379/3 作为结果后端 URL。

  • 运行 在 Docker 基础设施 应该有一个不同的 celeryconfig,它将 Celery 应用程序配置为使用 redis://localhost:6379/1 作为代理,并使用 redis://localhost:6379/3 作为结果后端。