多个码头工人容器和芹菜

  • 本文关键字:芹菜 码头 docker celery
  • 更新时间 :
  • 英文 :


我们现在有以下项目结构:

  1. 处理来自客户端的传入请求的 Web 服务器。
  2. 分析模块,为用户提供一些建议。

我们决定让这些模块完全独立,并将它们移动到不同的 docker 容器中。当用户的查询到达 Web 服务器时,它会向分析模块发送另一个查询以获取建议。

为了使建议保持一致,我们需要定期进行一些后台计算,例如,当新用户在我们的系统中注册时。此外,一些后台任务纯粹与 Web 服务器逻辑连接。为此,我们决定使用分布式任务队列,例如 Celery。

任务创建和执行有以下可能的情况:

在Web服务器上排队的任务,
  1. 在Web服务器上执行的任务(例如,处理上传的图像(
  2. 在Web服务器上排队的任务,在分析模块上执行的任务(例如,为新用户计算建议(
  3. 任务在分析模块上排队并在那里执行(例如,定期更新(

到目前为止,我在这里看到了 3 种相当奇怪的可能性:

I.芹菜放在单独的容器中,做所有事情

  1. 将芹菜移动到单独的 docker 容器。
  2. 提供来自Web服务器和分析的所有必要软件包来执行任务。
  3. 与其他容器共享任务代码(或在 Web 服务器和分析中声明虚拟任务(

这样,我们就可以松开隔离,因为功能由 Celery 容器和其他容器共享。

II. 芹菜放在单独的容器中,做得少得多

一样,但任务现在只是对 Web 服务器和分析模块的请求,它们在那里异步处理,结果在任务内轮询,直到它准备好。

这样,我们从拥有经纪人中受益,但所有繁重的计算都从 Celery 工人那里转移。

三、每个容器中分别装芹菜

  1. 在网络服务器和分析模块中运行芹菜。
  2. 将虚拟任务声明(分析任务(添加到 Web 服务器。
  3. 添加 2 个任务队列,一个用于 Web 服务器,一个用于分析。

这样,在Web服务器上安排的任务可以在分析模块中执行。但是,仍然必须在容器之间共享任务代码或使用虚拟任务,此外,还需要在每个容器中运行芹菜工作器。

最好的方法是什么,或者应该完全改变逻辑,例如,将所有东西都移到一个容器内?

首先,让我们澄清芹菜库(pip installsetup.py获得(和芹菜工作者之间的区别 - 这是从代理中取消任务排队并处理它们的实际过程。当然,您可能希望有多个工作线程/进程(例如,将不同的任务分离到不同的工作线程(。

假设您有两个任务:calculate_recommendations_taskperiodic_update_task,并且您想在单独的工作线程上运行它们,即recommendation_workerperiodic_worker。 将celery beat另一个进程,它每 x 小时将periodic_update_task排队进入代理。

此外,假设您有使用瓶子实现的简单Web服务器。

我假设你也想在docker中使用芹菜代理和后端,我会选择芹菜的推荐用法 - RabbitMQ作为代理,Redis作为后端。

所以现在我们有 6 个容器,我将将它们写成docker-compose.yml

version: '2'
services:
rabbit:
image: rabbitmq:3-management
ports:
- "15672:15672"
- "5672:5672"
environment:
- RABBITMQ_DEFAULT_VHOST=vhost
- RABBITMQ_DEFAULT_USER=guest
- RABBITMQ_DEFAULT_PASS=guest
redis:
image: library/redis
command: redis-server /usr/local/etc/redis/redis.conf
expose:
- "6379"
ports:
- "6379:6379"
recommendation_worker:
image: recommendation_image
command: celery worker -A recommendation.celeryapp:app -l info -Q recommendation_worker -c 1 -n recommendation_worker@%h -Ofair
periodic_worker:
image: recommendation_image
command: celery worker -A recommendation.celeryapp:app -l info -Q periodic_worker -c 1 -n periodic_worker@%h -Ofair
beat:
image: recommendation_image
command: <not sure>
web:
image: web_image
command: python web_server.py

构建recommendation_imageweb_image的 dockerFiles 都应该安装 Celery。只有recommendation_image应该有任务代码,因为工作人员将处理这些任务:

推荐Dockerfile:

FROM python:2.7-wheezy
RUN pip install celery
COPY tasks_src_code..

WebDockerfile:

FROM python:2.7-wheezy
RUN pip install celery
RUN pip install bottle 
COPY web_src_code..

其他映像(rabbitmq:3-management&library/redis可从docker hub获得,当您运行docker-compose up时,它们将自动拉取(。

现在事情是这样的:在Web服务器中,您可以通过字符串名称触发芹菜任务,并通过任务ID提取结果(不共享代码(web_server.py

import bottle
from celery import Celery
rabbit_path = 'amqp://guest:guest@rabbit:5672/vhost'
celeryapp = Celery('recommendation', broker=rabbit_path)
celeryapp.config_from_object('config.celeryconfig')
@app.route('/trigger_task', method='POST')
def trigger_task():
r = celeryapp.send_task('calculate_recommendations_task', args=(1, 2, 3))
return r.id
@app.route('/trigger_task_res', method='GET')
def trigger_task_res():
task_id = request.query['task_id']
result = celery.result.AsyncResult(task_id, app=celeryapp)
if result.ready():
return result.get()
return result.state

最后一个文件config.celeryconfig.py

CELERY_ROUTES = {
'calculate_recommendations_task': {
'exchange': 'recommendation_worker',
'exchange_type': 'direct',
'routing_key': 'recommendation_worker'
}
}
CELERY_ACCEPT_CONTENT = ['pickle', 'json', 'msgpack', 'yaml']

相关内容

  • 没有找到相关文章

最新更新