2015-04-08 9 views
17

Ich bin relativ neu für Docker, Sellerie und RabbitMQ.Sellerie & RabbitMQ läuft als Docker Container: Empfangene nicht registrierte Aufgabe des Typs '...'

In unserem Projekt haben wir zur Zeit die folgende Einstellung: 1 physischen Host mit mehreren Docker-Container ausgeführt wird:

1x rabbitmq: 3-Management-Container

# pull image from docker hub and install 
docker pull rabbitmq:3-management 
# run docker image 
docker run -d -e RABBITMQ_NODENAME=my-rabbit --name some-rabbit -p 8080:15672 -p 5672:5672 rabbitmq:3-management 

1x Sellerie Behälter

# pull docker image from docker hub 
docker pull celery 
# run celery container 
docker run --link some-rabbit:rabbit --name some-celery -d celery 

(th ere einige weitere Behälter sind, aber sie sollten nicht mit dem Problem)

Task-Datei alles tun müssen, um

Um Sellerie kennen zu lernen und ein bisschen RabbitMQ, habe ich eine tasks.py Datei auf dem physikalischen host:

from celery import Celery 

app = Celery('tasks', backend='amqp', broker='amqp://guest:[email protected]/') 

@app.task(name='tasks.add') 
def add(x, y): 
    return x + y 

Das ganze Setup scheint eigentlich ganz gut zu funktionieren. Also, wenn ich ein Python-Shell im Verzeichnis öffnen, in dem tasks.py befindet und laufe

>>> from tasks import add 
>>> add.delay(4,4) 

Die Aufgabe wird die Warteschlange gestellt und direkt aus dem Sellerie Arbeiter gezogen.

jedoch die Sellerie Arbeiter kennen nicht die Aufgaben Modul in Bezug auf die Protokolle:

$ docker logs some-celery 


[2015-04-08 11:25:24,669: ERROR/MainProcess] Received unregistered task of type 'tasks.add'. 
The message has been ignored and discarded. 

Did you remember to import the module containing this task? 
Or maybe you are using relative imports? 
Please see http://bit.ly/gLye1c for more information. 

The full contents of the message body was: 
{'callbacks': None, 'timelimit': (None, None), 'retries': 0, 'id': '2b5dc209-3c41-4a8d-8efe-ed450d537e56', 'args': (4, 4), 'eta': None, 'utc': True, 'taskset': None, 'task': 'tasks.add', 'errbacks': None, 'kwargs': {}, 'chord': None, 'expires': None} (256b) 
Traceback (most recent call last): 
    File "/usr/local/lib/python3.4/site-packages/celery/worker/consumer.py", line 455, in on_task_received 
strategies[name](message, body, 
KeyError: 'tasks.add' 

So ist das Problem offensichtlich zu sein scheint, dass die Sellerie Arbeiter im Sellerie Behälter nicht die Aufgaben Modul wissen. Jetzt, da ich kein Hafenarbeiter-Spezialist bin, wollte ich fragen, wie ich das Aufgaben-Modul am besten in den Sellerie-Container importieren würde?

Jede Hilfe ist willkommen :)


EDIT 2015.04.08, 21.05:

Dank Isowen für die Antwort. Nur der Vollständigkeit halber hier ist, was ich getan habe:

Nehmen wir an, meine tasks.py befindet sich auf meinem lokalen Rechner in /home/platzhersh/celerystuff. Jetzt habe ich ein celeryconfig.py im gleichen Verzeichnis mit folgendem Inhalt:

CELERY_IMPORTS = ('tasks') 
CELERY_IGNORE_RESULT = False 
CELERY_RESULT_BACKEND = 'amqp' 

Wie Isowen erwähnt, Sellerie sucht /home/user des Behälters für Aufgaben und Konfigurationsdateien. So montieren wir die /home/platzhersh/celerystuff in den Behälter beim Start:

run -v /home/platzhersh/celerystuff:/home/user --link some-rabbit:rabbit --name some-celery -d celery 

Dieser den Trick für mich. Ich hoffe, dies hilft anderen Menschen mit ähnlichen Problemen. Ich werde jetzt versuchen, diese Lösung zu erweitern, indem ich die Aufgaben auch in einen separaten Andock-Container lege.

+0

Warum verwenden Sie beide amqp und redis hier? –

+0

@JohnWu Entschuldigung für die späte Antwort, aber wir sind nicht? :) – platzhersh

Antwort

11

Wie Sie vermuten, liegt das Problem daran, dass der Selleriearbeiter das Aufgabenmodul nicht kennt. Es gibt zwei Dinge, die Sie tun müssen:

  1. Holen Sie sich Ihre Aufgaben Definitionen "in" den Docker Container.
  2. Konfigurieren Sie den Sellerie-Arbeiter zum Laden dieser Aufgabendefinitionen.

Für Item (1) ist der einfachste Weg wahrscheinlich die Verwendung eines "Docker Volume", um ein Hostverzeichnis Ihres Codes auf der Sellery Docker Instanz zu mounten. Etwas wie:

docker run --link some-rabbit:rabbit -v /path/to/host/code:/home/user --name some-celery -d celery 

Wo /path/to/host/code ist der Host-Pfad und /home/user ist der Weg, es auf die Instanz zu montieren. Warum /home/user in diesem Fall? Weil das Dockerfile für das Selleriebild das Arbeitsverzeichnis (WORKDIR) als /home/user definiert.

(Anmerkung: Ein andere Möglichkeit, Artikel zu erreichen (1) würde ein benutzerdefinierte Docker Bild mit dem Code „eingebauten“ zu bauen, aber ich will, dass für den Leser als Übung überlassen.)

Für Artikel (2), müssen Sie eine Sellerie-Konfigurationsdatei erstellen, die die Task-Datei importiert. Dies ist ein allgemeineres Problem, daher werde ich auf eine vorherige Stackoverflow-Antwort zeigen: Celery Received unregistered task of type (run example)

+0

Hey Isowen, danke für diese schnelle Antwort! Ich habe bereits versucht, die Datei tasks.py zu mounten, wusste aber nicht, dass ich sie in/home/user einbinden musste. Wo würde ich die Selleryconfig setzen? Auch/home/Benutzer? Eigentlich wollen wir am Ende Aufgaben von mehreren verschiedenen Hosts übernehmen, also müssten wir neben dem Einbinden aller Task-Dateien eine gute Lösung finden. Aber das ist im Moment in Ordnung, um zu sehen, ob eine grundlegende Einrichtung funktionieren würde. – platzhersh

+1

@platzhersh Sie könnten tatsächlich in ein anderes Verzeichnis mounten, aber dann wäre es nicht das 'PWD' von Sellerie, wenn es ausgeführt wird, also würde das Hinzufügen des Codes zum Python-Suchpfad einen zusätzlichen Schritt erfordern. Mit anderen Worten, am einfachsten zu verwenden '/ home/user'. Ich hoffe, das hilft! – lsowen

+1

@platzhersh auf lange Sicht sollten Sie ein Docker-Image erstellen, das Ihre Aufgaben enthält. –