使用 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
作为结果后端。
我已经使用 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
作为结果后端。