我最近开始使用Docker + Celery。我还分享了full sample codes for this example on github,下面是其中的一些代码段,以帮助解释我的观点。
对于上下文,我的示例被设计为一个预订微服务系统中的事件的节点。在此节点中,它包含以下服务:
服务在docker-compose.yml
文件中定义如下:
version: "3.7"
services:
# To launch the Subscriber (using Kombu incl. in Celery)
subscriber:
build: .
tty: true
#entrypoint: ...
# To launch Worker (Celery)
worker:
build: .
entrypoint: celery worker -A worker.celery_app --loglevel=info
depends_on:
- redis
redis:
image: redis
ports:
- 6379:6379
entrypoint: redis-server
为简单起见,我省略了 subscriber 的代码,我认为在此示例中,在 subscriber容器中使用python交互式外壳就足够了:
python3
>>> from worker import add
>>> add.delay(2,3).get()
5
并在工人容器日志中:
worker_1 | [2020-09-17 10:12:34,907: INFO/ForkPoolWorker-2] worker.add[573cff6c-f989-4d06-b652-96ae58d0a45a]: Adding 2 + 3, res: 5
worker_1 | [2020-09-17 10:12:34,919: INFO/ForkPoolWorker-2] Task worker.add[573cff6c-f989-4d06-b652-96ae58d0a45a] succeeded in 0.011764664999645902s: 5
虽然一切似乎都正常,但我感到不安。我以为这个示例不尊重Docker容器的隔离原理。
容器不是旨在隔离其操作系统级别的, 流程和网络?而且如果容器必须进行通信,则不应该通过IP地址和网络协议(TCP / UDP等)完成
首先,在我的示例中, worker 和 subscriber 运行相同的代码库,因此import语句上不会出现任何问题。
但是,芹菜工作者是从 worker容器中的entrypoint
启动的,因此 subscriber 如何设法在应该隔离的工人容器?
要进一步验证它实际上是从 worker容器调用celery worker实例,我停止了 worker容器,并在< strong>用户容器。再次打开工作容器后,请求将等待(这是芹菜的预期结果),并返回相同的结果。因此,IMO,是的,来自一个容器的服务正在从另一个容器调用应用程序实例,而没有网络连接,例如连接到Redis(使用IP地址等)。
请告知我的理解是不正确的,还是我不知道的地方可能有错误的实现。
答案 0 :(得分:0)
消费者(工作人员)和生产者(子投标人)都配置为将Redis(redis)用作代理和结果后端。这就是为什么一切正常的原因。 -当您在订阅者容器中执行add.delay(2,3).get()
时,它会将任务发送给Redis,然后它被运行在另一个容器中的Celery工作人员选择。
请记住,运行add.delay(2,3).get()
代码的Python进程正在订阅者容器中运行,而执行add()函数并将结果存储在结果后端中的ForkPoolWorker-2
进程正在worker容器中运行。这些过程是完全独立的。
订阅者进程未调用辅助容器中的任何内容! -用简单的英语说,这是我的工作:“在Redis中,这是我需要做的,请工作人员完成,并让我知道您已完成,以便我获取结果。”
答案 1 :(得分:0)
Docker-compose为在单个文件中创建的容器创建默认的docker网络。由于您正确地指向了所有内容,因此它将沿着该网络发出请求,这就是成功的原因。听说如果您要在不使用docker-compose的情况下并行并行运行每个容器,这种方法仍然有效,我会感到惊讶。