多个 Docker 容器和 Celery

2024-04-26

我们现在的项目结构如下:

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

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

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

任务创建和执行可能有以下几种场景:

  1. 在网络服务器上排队并在网络服务器上执行的任务(例如,处理上传的图像)
  2. 在网络服务器上排队的任务,在分析模块上执行(例如,计算新用户的推荐)
  3. 任务在分析模块中排队并在那里执行(例如,定期更新)

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

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

  1. 将 Celery 移至单独的 docker 容器。
  2. 提供网络服务器和分析中执行任务所需的所有包。
  3. 与其他容器共享任务代码(或在网络服务器和分析中声明虚拟任务)

这样,我们就放松了隔离,因为功能是由 Celery 容器和其他容器共享的。

二.芹菜放在单独的容器中,作用要少得多

Same as I,但任务现在只是对 Web 服务器和分析模块的请求,这些请求在那里异步处理,结果在任务内部轮询直到准备好。

这样,我们就可以从代理中获益,但所有繁重的计算都从 Celery 工作线程中转移。

三.将芹菜分别放入每个容器中

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

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

做到这一点的最佳方法是什么,或者应该完全改变逻辑,例如,将所有内容移动到一个容器内?


首先,让我们澄清一下 celery 库(你可以用它得到的)之间的区别pip install或者在你的setup.py)和芹菜worker- 这是从代理中取出任务并处理它们的实际过程。当然你可能想要多个workers/processes(例如,用于将不同的任务分离给不同的工作人员)。

假设您有两个任务:calculate_recommendations_task and periodic_update_task并且您想在单独的工作人员上运行它们,即recommendation_worker and periodic_worker。 另一个过程将是celery beat这只是排队periodic_update_task每 x 小时进入经纪商。

另外,假设您有一个简单的 Web 服务器,使用以下方法实现bottle https://bottlepy.org/docs/dev/.

我假设您也想将 celery 代理和后端与 docker 一起使用,我将选择 celery 的推荐用法 -RabbitMQ https://www.rabbitmq.com/作为经纪人和Redis https://redis.io/作为后端。

现在我们有 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

两个 dockerfiles,它构建了recommendation_imageweb_image应该安装芹菜library。只有recommendation_image应该有任务代码,因为工作人员将处理这些任务:

推荐 Dockerfile:

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

WebDocker 文件:

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).

现在事情是这样的:在你的网络服务器中,你可以通过字符串名称触发 celery 任务,并通过任务 ID 提取结果(无需共享代码)网络服务器.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

最后一个文件配置.celeryconfig.py:

CELERY_ROUTES = {
    'calculate_recommendations_task': {
        'exchange': 'recommendation_worker',
        'exchange_type': 'direct',
        'routing_key': 'recommendation_worker'
    }
}
CELERY_ACCEPT_CONTENT = ['pickle', 'json', 'msgpack', 'yaml']
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

多个 Docker 容器和 Celery 的相关文章

  • 在 Celery 工作线程中捕获 Heroku SIGTERM 以优雅地关闭工作线程

    我对此进行了大量研究 令我惊讶的是我还没有在任何地方找到一个好的答案 我正在 Heroku 上运行一个大型应用程序 并且我有某些运行很长时间处理的 celery 任务 并在任务结束时保存结果 每次我在 Heroku 上重新部署时 它都会发送
  • 验证来自两个不同 URL 的 Keycloak 令牌

    我有一个Docker compose具有后端和前端组件的基于系统 后端写的是Python Flask并在多个 docker 容器中运行 前端编写为TypeScript with Angular 前端通过Restful API与后端进行通信
  • Docker 与 nginx 组合不断显示欢迎页面

    我是新来的docker并尝试使用最简单的 docker compose yml 显示一个 hello world 页面 并在此基础上构建最终完整的LEMP堆栈它将与我的服务器具有相同的配置 然而大多数教程已经过时 并且有很多使用方法dock
  • Docker - Spring Boot 应用程序 - 无法访问本地主机上的 MySql 服务器

    如何将在 Docker 中运行的 Spring Boot JAR 应用程序连接到我计算机上的 MySql 服务器 我尝试了不同的帖子 但这没有帮助 在我的 Spring Boot application properties 中 我有 sp
  • Visual Studio 2015 Docker 集成不会附加调试

    我使用 VS 2015 创建了一个 Default net Core RC2 MVC 应用程序 我添加了 Docker 支持 以便我可以在 docker 中运行和调试它 当我运行该项目时 它会构建 docker 容器并启动它 运行命令 do
  • 如何在 kubernetes 中传递命令行参数?

    需要在 pod yaml 中传递 docker 容器 appContainer1 和 appContainer2 的命令行参数 pod yaml apiVersion v1 kind Pod metadata name microservi
  • Docker容器总是显示ssl连接错误

    我正在开始使用 docker compose 并一直在研究简单的演示 Flask 应用程序 问题是 我在一个组织内部运行这个程序 该组织以左右抛出 SSL 错误的方式拦截所有通信 他们为我们提供了需要安装的三个根证书 我通常已经让这些证书在
  • 无法在 Docker 下运行 AWS SAM CLI

    我正在尝试创建一个 Docker 镜像AWS SAM CLI https github com awslabs aws sam cli 但调用任何函数都会出现错误 无法导入模块 index 我可以在 Docker 之外成功运行相同的测试用例
  • 在 docker windows 上运行 linux 容器

    我在 Windows 10 机器上安装了 Docker for Windows 它要求我启用 HyperV 功能 一切都安装正确并且运行良好 虽然有一件事让我大吃一惊 我实际上能够在 docker windows 上运行 Linux 容器
  • 无法从 docker 容器打开 URL

    我在从 Docker 容器导航到 Google 身份验证页面时遇到问题 该应用程序是使用 asp net Core 2 0 制作的 其目的是显示从 Google Calendar API 检索的即将发生的事件 并在需要时创建事件 当应用程序
  • 是否可以对不同的服务使用不同的 .env?

    我遇到一种情况 最好有多个 env 文件 每个 env 文件对应 docker compose yml 中的每个服务 有什么方法可以指定要使用的不同文件名吗 这可以在个人服务层面上做到吗 我尝试使用env file不幸的是 这设置了在 Do
  • Kubernetes 1.8 支持的 Docker 版本

    我要将我的 Kubernetes 集群升级到该版本1 8 7 有谁知道哪个 docker 版本与其最兼容 这是我在 Kubernetes 官方页面上找到的 但我想它可能是针对最新的 k8s 版本的 1 9 在每台计算机上安装 Docker
  • 如何在 App Engine 中灵活更改 /dev/shm 的大小

    如何更改共享内存文件夹的大小 dev shm在 App Engine 灵活应用程序中 默认情况下 它设置为 64M 太低 无法运行许多应用程序 例如 Chrome 我看不出有什么办法可以改变它 如果您有权访问 可以通过多种方法进行更改doc
  • 在 Dockerfile 中安装节点?

    我是AWS elastic beanstalk的用户 我遇到了一些问题 我想用 less node 构建我的 CSS 文件 但我不知道在使用 jenkins 构建时如何在 dockerfile 中安装节点 这是我在 docker 中使用的安
  • Postgres 到 Ubuntu Docker 容器的链接不起作用

    编辑 我可以在没有任何我自己的自定义代码的情况下重现此内容 我刚刚创建了一个运行 Ubuntu 14 04 的新 Linode 映像 并按照以下步骤安装了 DockerDocker 的网站 https docs docker com ins
  • django celery - 如何将 request.FILES['photo'] 发送到任务

    我正在尝试通过以下方式将 request FILES photo 从我的网站上传的文件 发送到 tCelery tasks upload photos delay img request FILES photo 我收到 pickle 错误
  • 从 celery 工作人员到普罗米修斯的自定义指标

    我有一些 celery 工作人员在 kubernetes 下的容器中运行 它们不会由 celery 自动缩放 并且每个都在单个进程中运行 即没有多处理 我想从他们那里获取一堆不同的指标到普罗米修斯中 我研究过 celery promethe
  • 与主机中的容器共享目录或卷

    我有一个目录 可能是后面的卷 我想与所有交互式容器共享 我知道 本机 Docker 卷存储在 var lib docker volumes and docker run v似乎是最简单的方法 但我认为Data Volume Containe
  • JFrog Artifactory 将什么令牌端点用于其 Docker 注册表?

    我正在尝试编写基本上可以执行以下操作的代码docker inspect发布到私人 JFrog Artifactory 的图像 而无需自己实际提取图像 我一直在使用一个名为在不拉取的情况下检查 Docker 镜像 https ops tips
  • 从 Dockerfile 写入 docker 卷不起作用

    请考虑以下 Dockerfile FROM phusion baseimage VOLUME data RUN touch data HELLO RUN ls ls data 问题 data 目录不包含 HELLO 文件 此外 任何其他写入

随机推荐

  • Android Studio v 1.1 / 1.2 中的渲染问题

    当我添加android support v7 widget Toolbar或其他android support v7 widget 存在渲染问题 But 支持库已是最新 我正确地编译了依赖项 我可以将它们导入MainActivity jav
  • 我可以为第二个侧边栏使用多个

    我可以使用多个吗
  • 安装Python时出错

    击中后 make install 我收到以下错误 usr bin install cannot create regular file usr local bin python2 6 Permission denied make altbi
  • 如何更改每个 Gradle 构建类型的应用程序名称

    我正在尝试找出一种方法来更改 gradle 中每个构建类型的应用程序的应用程序名称 例如 我希望调试版本具有
  • Winforms RichTextBox 中的两列

    在 C 中 我需要能够在单个 RichTextBox 中至少给出 2 列的印象 出于我的目的 它可能看起来像这样 1 1 2 70 8 5 565 1000000 300000 700000 76 10 66 对于左栏中的每个 问题 都会有
  • Aurelia 中的多个触发器

    我想在 aurelia 中触发两种不同的方法 实现此目的的最佳方法是什么 a 我可能会做以下事情 HTML a JavaScript yourFunction event parts this toggleSize size parts t
  • 在触发器上传递 JSON 数据

    我正在调用返回 JSON 数据的服务 Script ajax type POST url some service dataType json success function response if response status ok
  • MongoDB 推文数据库的日期范围查询失败

    我正在尝试对 mongo 数据库中的推文集合执行范围查询 由于某种原因 以下查询将起作用 db posts find created at gte Fri Nov 25 00 00 00 0000 2011 lt Fri Nov 25 23
  • 从节点子进程检索值

    var fp ffprobe fileName show streams grep var width exec fp width function err stdout stderr return stdout alert stdout
  • NgbDropdown autoClose“外部”不起作用

    我正在使用 Angular4 和 ng bootstrap 我想在下拉菜单外部单击时关闭下拉菜单 文档的其余部分 查看文档后我发现autoClose 类型 boolean 外面 里面 但是当我尝试将其设置为参数 config autoClo
  • 是否可以在浏览器中使用 javascript 对用户系统进行基准测试

    随着 Html5 开始普及 我们看到更多关于视频或画布元素等的实验 当使用画布进行实验时 例如用粒子制作烟花 1000 个粒子可能在现代机器上运行良好 但在 3 年机器上可能会运行得很慢 无论如何 是否可以对用户系统进行基准测试以动态更改画
  • 当摘要具有嵌入文本输入并且用户按空格键时,如何防止 html 详细信息元素切换

    我在处于打开状态的详细信息元素的摘要标签内有一个文本输入 目的是捕获用户输入 该输入最终将显示为详细信息元素 见下文 但是 当用户在输入文本时按空格键时 详细信息元素会切换 我想阻止这种情况 我预计这可以在按键事件中使用 stopPropa
  • xgboost中的eval_metric和feval有什么区别?

    有什么区别feval and eval metric在xgb train中 这两个参数仅用于评估目的 Kaggle 的帖子提供了一些见解 https www kaggle com c prudential life insurance as
  • Java、类路径、类加载 => 同一 jar/项目的多个版本

    我知道对于经验丰富的程序员来说这可能是一个愚蠢的问题 但我有一个库 一个 http 客户端 我的项目中使用的一些其他框架 jar 需要它 但它们都需要不同的主要版本 例如 httpclient v1 jar gt Required by c
  • 迭代器后继者

    我想用另一个迭代器 同类 的后继者初始化一个迭代器 任意类型 以下代码适用于随机访问迭代器 但不适用于前向或双向迭代器 Iterator i j 1 一个简单的解决方法是 Iterator i j i 但这不起作用初始化语句for 循环的
  • 如何通过分页从附加页面中提取数据

    我成功返回了第一页数据 并获得了 API 调用中存在的附加数据页数 这是我尝试提取附加数据页的代码 try const response UrlFetchApp fetch root endpoint params const respon
  • 如何从右向左对齐日期选择器?

    datepicker dob on click function datepicker datepicker format dd mm yyyy autoclose true
  • 设计评论表

    基本上我想创建一个评论系统 其中评论可能有也是评论的父母 但我也希望他们可能有可能是其他东西的父母 例如用户或产品 即 我希望能够对产品发表评论 用户 其他评论或几乎任何资源 我该怎么做呢 当前表 标签 产品 用户 评论 编辑 这将适用于流
  • jQuery 获取容器的 html,包括容器本身

    我如何获取 container 上的 html 包括 container 而不仅仅是其中的内容 div div test 1 div div test 2 div div test 3 div div test 4 div div 我有这个
  • 多个 Docker 容器和 Celery

    我们现在的项目结构如下 处理来自客户端的传入请求的 Web 服务器 向用户提供一些建议的分析模块 我们决定保持这些模块完全独立 并将它们移动到不同的 docker 容器中 当用户的查询到达网络服务器时 它会向分析模块发送另一个查询以获取推荐