2016-03-17 54 views
7

Continuo a incorrere in problemi di mysql wierd mentre i lavoratori eseguono le attività subito dopo la creazione.Creazione di una connessione di database separata per ogni operatore di sedano

Usiamo Django 1.3, sedano 3.1.17, djorm-ext-piscina 0,5

Iniziamo processo di sedano con la concorrenza 3. mio obeservation finora è, quando l'inizio del processo di lavoratori, hanno trovato e troveranno stessa mysql connecition. Registriamo l'ID della connessione db come di seguito.

from django.db import connection 
connection.cursor() 
logger.info("Task %s processing with db connection %s", str(task_id), str(connection.connection.thread_id())) 

Quando tutti i lavoratori ottengono compiti, il primo eseguito con successo, ma gli altri due dà strani errori di MySQL. Errori con "Mysql server andato via" o con una condizione in cui Django genera l'errore "DoesNotExist". chiaramente gli oggetti che Django sta interrogando esistono.

Dopo questo errore, ciascun operatore inizia a ricevere la propria connessione al database, dopodiché non troviamo alcun problema.

Qual è il comportamento predefinito di sedano? È progettato per condividere la stessa connessione al database. In caso affermativo, come viene gestita la comunicazione tra processi? Preferirei preferire una connessione di database diversa per ogni lavoratore.

Ho provato il codice indicato nel link sottostante che non ha funzionato. Celery Worker Database Connection Pooling

Abbiamo anche corretto il codice di sedano suggerito di seguito. https://github.com/celery/celery/issues/2453

Per coloro che non rispondo alla domanda, cortesemente fammi sapere il motivo del downvote.

+0

Stai utilizzando qualsiasi middleware per il pooling di connessioni Django? Inoltre, qual è il tuo 'CONN_MAX_AGE' nella configurazione di django? Penso che questo abbia un comportamento persistente di connessione nel django. Questo potrebbe essere correlato al comportamento che stai vedendo, non qualcosa con Celery stesso. –

+0

Potresti eseguire concurrency = 1 e avviare più worker? –

+0

@AlexLuisArias Avrebbe eseguito solo un processo di lavoro e non è un caso per il problema precedente. –

risposta

2

sedano è iniziato con il comando di seguito

celery -A myproject worker --loglevel=debug --concurrency=3 -Q testqueue 

myproject.py come parte del processo di maestro stava facendo alcune query al database MySQL prima di sborsare i processi di lavoro.

Come parte del flusso di query nel processo principale, django ORM crea un pool di connessioni sqlalchemy se non esiste già. I processi di lavoro sono quindi creati.

Il sedativo come parte delle correzioni di django chiude le connessioni esistenti.

def close_database(self, **kwargs): 
    if self._close_old_connections: 
     return self._close_old_connections() # Django 1.6 
    if not self.db_reuse_max: 
     return self._close_database() 
    if self._db_recycles >= self.db_reuse_max * 2: 
     self._db_recycles = 0 
     self._close_database() 
    self._db_recycles += 1 

In effetti quello che potrebbe accadere è che, l'oggetto piscina sqlalchemy con una connessione db non utilizzata viene copiato il processo di 3 lavoratori quando biforcuta. Quindi i 3 diversi pool hanno 3 oggetti di connessione che puntano allo stesso descrittore del file di connessione.

I lavoratori durante l'esecuzione delle attività quando viene richiesta una connessione DB, tutti i lavoratori ottengono la stessa connessione inutilizzata dal pool sqlalchemy perché non è attualmente in uso. Il fatto che tutte le connessioni puntino allo stesso descrittore di file ha causato errori nella connessione MySQL.

Nuove connessioni create lì dopo sono tutte nuove e non puntano allo stesso descrittore di file socket.

Soluzione:

Nel processo principale aggiungere

from django.db import connection 
connection.cursor() 

prima di ogni importazione è fatto. prima che venga aggiunto anche il modulo djorm-ext-pool.

In questo modo tutte le query db utilizzeranno la connessione creata da django all'esterno del pool. Quando la correzione di celery django chiude la connessione, la connessione viene effettivamente chiusa anziché tornare al pool di alchimia lasciando il pool di alchimia senza connessioni al momento di far fronte a tutti gli operatori quando sono biforcati. Lì dopo, quando i lavoratori chiedono la connessione db, sqlalchemy restituisce una delle connessioni appena create.