Bienvenue sur IndexError.

Ici vous pouvez poser des questions sur Python et le Framework Django.

Mais aussi sur les technos front comme React, Angular, Typescript et Javascript en général.

Consultez la FAQ pour améliorer vos chances d'avoir des réponses à vos questions.

Problème de tâches groupées avec Celery

+2 votes

J'ai un problème bizarre avec Celery et Redis sous GNU/Linux que je n'ai pas sous Windows.

J'ai un canvas de tâches pour des imports de données qui fonctionne très bien et nous avons identifié qu'il était possible de faire certaines tâches simultanément, alors naïf comme nous sommes nous avons créé des groupes que nous avons chainés. Ca donne un truc comme ça :

group_1 = group(
    importer_organismes.s(),
    importer_entreprises.s(),
    importer_caisses_assurance.s(),
)

group_2 = group(
    importer_populations.s(),
)

group_3 = group(
    importer_contrats_collectifs.s(),
    importer_contrats_individuels.s(),
)

group_4 = group(
    importer_personnes.s(),
    importer_produits.s(),
)

group_5 = group(
    importer_adresses.s(),
    importer_domiciliations_bancaires.s(),
    importer_numeros_insee.s(),
    importer_parametres_personnes.s(),
    importer_liens_caisse_personne.s(),
    verifier_personnes.s(),
)

workflow = chain(
    group_1,
    merge.s(),
    group_2,
    merge.s(),
    group_3,
    merge.s(),
    group_4,
    merge.s(),
    group_5,
    merge.s(),
)

context = Context()
return workflow.apply_async(args=(context, ))

Entre chaque groupe, nous avons mis une sous-tâche permettant de récolter toutes les données de sortie et d'en faire un unique conteneur.

Quand nous exécutons le canvas sous GNU/Linux, le premier groupe s'exécute mais seulement importer_entreprises ou importer_organismes et importer_caisses_assurance ensemble, c'est assez aléatoire, mais jamais les 3 en même temps. Pire encore, une fois ces tâches terminées (avec succès), elles ne passent pas le relais aux suivantes !

Bref, on ne trouve pas de solution après avoir épluché la documentation et le web.

Configuration Celery

# Celery configuration
BROKER_URL = 'redis://localhost:6379/0'
BROKER_TRANSPORT_OPTIONS = {
    'visibility_timeout': 43200,
    'fanout_prefix': True,
    'fanout_patterns': True,
}
CELERY_TASK_SERIALIZER = 'pickle'
CELERY_RESULT_SERIALIZER = 'pickle'
CELERY_RESULT_BACKEND = 'redis://localhost:6379/1'
CELERY_ACCEPT_CONTENT = ['pickle', 'json', 'msgpack', 'yaml']
CELERY_DISABLE_RATE_LIMITS = True
CELERY_ALWAYS_EAGER = False

Celery runner (Django)

# coding: utf-8
import os
from celery import Celery

# Logging
import logging
log = logging.getLogger(__name__)

# Set the default Django settings module for the 'celery' program.
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'nouvelleoffre.settings')

# Load environment configuration
from configurations import importer
importer.install()

app = Celery('nouvelleoffre')

# Django setup (only for Django 1.7)
# from django imports setup
# setup()

# Using a string here means the worker will not have to
# pickle the object when using Windows.
app.config_from_object('django.conf:settings')

# Auto-discover celery tasks inside Django applications
from django.conf import settings
app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)

Lancement du worker

NAME="demo"
DJANGODIR=/home/demo/demo
NUM_WORKERS=1
DJANGO_SETTINGS_MODULE=nouvelleoffre.settings
DJANGO_CONFIGURATION=Staging
DJANGO_WSGI_MODULE=nouvelleoffre.wsgi

# Activate the virtual environment
cd $DJANGODIR
# source /home/demo/.pyenv/versions/nouvelleoffre/bin/activate
export DJANGO_SETTINGS_MODULE=$DJANGO_SETTINGS_MODULE
export DJANGO_CONFIGURATION=$DJANGO_CONFIGURATION
export PYTHONPATH=$DJANGODIR:$PYTHONPATH

# Create the run directory if it doesn't exist
RUNDIR=$(dirname $SOCKFILE)
test -d $RUNDIR || mkdir -p $RUNDIR

PYENV=/home/demo/.pyenv/versions/demo/bin
# Start your Django Celery workers
# Programs meant to be run under supervisor should not daemonize themselves (do not use --daemon)
exec $PYENV/celery worker -A nouvelleoffre --loglevel=INFO --logfile=logs/celery.log --without-mingle --without-gossip
demandé 2-Fev-2015 par debnet (1,022 points)

Si tu precises "sous linux", c'est que le souci est lié a l'environnement d'execution. Va falloir trouver ce qui differe entre l'env linux et l'env windows.

Difficile à identifier.

A la fois sous GNU/Linux et Windows, nous utilisons une version compilée de Python 3.4 avec un environnement virtuel dédié au projet, les deux déploiement partagent donc le même environnement et les mêmes dépendances.

Nous utilisons Redis comme broker et result backend, l'instance est plus utilisée sur le serveur GNU/Linux car il sert également à Sentry. En jouant avec les différentes "bases de données" de Redis nous remarquons un comportement différent, c'est assez perturbant.

Bref, on nage dans le brouillard et ça nous inquiète pour le déploiement client.

J'ai envie de lancer la pierre à Redis :\ sans en etre sur, je pense qu'il joue bien son role de backend, mais ne garde pas les resultats assez longtemps, ou alors, peut etre que quelque chose d'autre ecrase les resulats.

Si vous nagez dans le brouillard, faut demonter l'affaire. Peux tu tester vite fait avec un autre backend? eventuellement avec un autre broker?

Je viens de mettre en place RabbitMQ à la place de Redis, à la fois pour le broker et pour le result backend, et j'ai plus ou moins le même résultat.

En l'occurrence, j'ai une tâche qui s'exécute dans mon premier groupe alors qu'il devrait y en avoir 3 simultanément et mon canvas s'arrête après.

Voici le log du worker Celery :

[2015-02-03 17:09:20,169: INFO/MainProcess] Task imports.entreprises[57ad8684-0fc1-413a-a3f5-07577238a784] succeeded in 30.436586156999994s: {'migration_complete': True, 'entreprises': {2051: 853, 136193: 324, 2056: 559, 172048: 122, 230406: 243, 159783: 13, 253992:...
[2015-02-03 17:09:20,187: INFO/MainProcess] Task celery.chord_unlock[e564f003-cacf-4c5e-8e1e-5d1a07c8ec67] retry: Retry in 1s
[2015-02-03 17:09:21,592: INFO/MainProcess] Received task: celery.chord_unlock[e564f003-cacf-4c5e-8e1e-5d1a07c8ec67] eta:[2015-02-03 17:09:22.584924+01:00]

Donc on a isolé le problème des messages et des résultats, y a un donc un soucis avec Celery... mais lequel ?

D'ailleurs il s'avère que la dernière ligne dans le log se répète toutes les secondes à l'infini... Encore un bug ?...

J'ai plus d'idée. Essaye de changer de distribution, je dis ça betement. Sinon, la seule chose que je puisse te conseiller, c'est de continuer a demonter le script, groupe apres groupe, task apres task, en testant chaque morceau les uns a la suite des autres.

Je réinstalle l'environnement Python et les dépendances, mais j'y crois pas.

Ca marchait avant sur ce système, je ne vois pas pourquoi du jour au lendemain ça ne fonctionne plus...

1 Réponse

+1 vote
 
Meilleure réponse

Apparemment le problème venait du fait que nous avions deux instances de workers lancés (pour deux versions du code source différent mais avec le même nom), ce qui provoquait ce dysfonctionnement.

Nous continuons les tests dans ce sens afin de vérifier que c'était bien la cause puis j'éditerai ce message pour valider la solution.

Par contre, il reste toujours un bug avec Celery et RabbitMQ concernant la libération des chord qui ne se fait pas et qui réessaye toutes les secondes... si quelqu'un à une idée pour celle-là ça serait génial ! :D

répondu 4-Fev-2015 par debnet (1,022 points)
sélectionné 5-Fev-2015 par debnet

Tu as le droit d'accepter ta propre réponse. Ca permet de voir qu'elle a été résolue. Pour le deuxième problème, ouvre une seconde question.

...