web-dev-qa-db-fra.com

Connexion de la base de données de l'ouvrier de céleri

J'utilise le célery autonome (pas à Django). Je prévois d'avoir un type de tâche travailleur exécuté sur plusieurs machines physiques. La tâche fait ce qui suit

  1. Acceptez un document XML.
  2. Transformez-le.
  3. Faire -multiple Database lit et écrit.

J'utilise PostgreSQL, mais cela s'appliquerait également à d'autres types de magasins utilisant des connexions. Dans le passé, j'ai utilisé un pool de connexion de base de données pour éviter de créer une nouvelle connexion de base de données sur chaque demande ou d'éviter de garder la connexion ouverte trop longtemps. Cependant, étant donné que chaque travailleur de céleri fonctionne dans un processus séparé, je ne suis pas sûr de la manière dont ils seraient en mesure de partager la piscine. Est-ce que je manque quelque chose? Je sais que le célery vous permet de persister un résultat renvoyé d'un travailleur de céleri, mais ce n'est pas ce que j'essaie de faire ici. Chaque tâche peut effectuer plusieurs mises à jour ou insertions différentes en fonction des données traitées.

Quelle est la bonne façon d'accéder à une base de données d'un travailleur de céleri?

Est-il possible de partager une piscine sur plusieurs travailleurs/tâches ou y a-t-il une autre façon de le faire?

32
oneself

J'aime l'idée d'un lien de Tigeronk2 par travailleur. Comme il le dit, le céleri conserve son propre pool de travailleurs, il n'est donc pas vraiment nécessaire de disposer d'un pool de connexion de base de données séparé. Le Signal de célery Docs Expliquez comment faire une initialisation personnalisée Lorsqu'un travailleur est créé, j'ai donc ajouté le code suivant à mes tâches. Pouvoir et il semble fonctionner exactement comme vous l'attendez. J'étais même capable de fermer les connexions lorsque les travailleurs sont arrêtés:

db_conn = None

@worker_process_init.connect
def init_worker(**kwargs):
    global db_conn
    print('Initializing database connection for worker.')
    db_conn = db.connect(DB_CONNECT_STRING)


@worker_process_shutdown.connect
def shutdown_worker(**kwargs):
    global db_conn
    if db_conn:
        print('Closing database connectionn for worker.')
        db_conn.close()
24
ThatAintWorking

Avoir une connexion DB par processus de travailleur. Étant donné que le céleri lui-même maintient un bassin de processus de travail, vos connexions DB seront toujours égales au nombre de travailleurs de céleri. Flip côté, en quelque sorte, il liera la connexion de la connexion à DB à la gestion des processus de travailleur de céleri. Mais cela devrait être bien étant donné que Gil ne permet qu'un seul fil à la fois dans un processus.

3
tigeronk2

Vous pouvez remplacer le comportement par défaut pour avoir des travailleurs filetés au lieu d'un travailleur par processus dans votre configuration de céleri:

CELERYD_POOL = "celery.concurrency.threads.TaskPool"

Ensuite, vous pouvez stocker l'instance de pool partagée sur votre instance de tâche et la référencer à chaque invocation des tâches filetées.

2
Loren Abrams

Peut-être que vous pouvez utiliser pgbouncer . Pour le céleri, rien ne devrait changer et la mise en commun de la connexion est effectuée en dehors des processus. J'ai la même chose problème .

("Peut-être" parce que je ne suis pas sûr s'il pourrait y avoir des effets secondaires)

1
kev