2009-10-21 3 views
7

Ho un'applicazione Rails in cui un numero limitato di azioni richiede un tempo di calcolo significativo. Piuttosto che passare attraverso la complessità della gestione di queste azioni come attività in background, ho scoperto che posso dividere l'elaborazione in più thread e utilizzando JRuby con un sever multicore, posso assicurarmi che tutti i thread vengano completati in un tempo ragionevole. (Il cliente ha già manifestato un forte interesse a mantenere questo approccio rispetto alle attività in background.)Registrazione all'interno di thread in un'applicazione Rails

Il problema è che la scrittura nel registratore di Rails non funziona all'interno di questi thread. Nulla si presenta nel file di registro. Ho trovato alcuni riferimenti a questo problema ma nessuna soluzione. Non mi dispiacerebbe inserire insert nel mio codice per aiutare con il debug, ma lo stdout sembra essere consumato dal server dell'app gemma glassfish.

Qualcuno ha eseguito correttamente la registrazione in un thread di rubini Rails senza creare un nuovo registro ogni volta?

+0

Aggiornamento: ho scoperto che le discussioni nei thread si presentano nel file di registro glassfish. Non sono sicuro del motivo per cui non l'ho visto prima; Potrei averlo testato originariamente in un thread generato da un altro thread (non principale). Comunque, a scopo di debug, sto vedendo le scritture su STDOUT nel file di log, quindi sono felice. –

risposta

4

Mi stavo grattando la testa con lo stesso problema. Per quanto mi riguarda, la risposta è stata la seguente:

Thread.new do 
    begin 
    ... 
    ensure 
    Rails.logger.flush 
    end 
end 
+0

Sembra buono! Grazie! –

+0

Non funziona per me, usando EM – skrat

0

Comprendo le tue preoccupazioni in merito alle attività in background, ma ricorda che la rotazione di thread in Rails può essere una cosa spaventosa. Il framework non prevede disposizioni per il multithreading, il che significa che devi considerare tutti gli oggetti Rails come non thread-safe. Anche la connessione al database diventa complicata.

Come per il logger: la classe standard del logger di Ruby deve essere protetta da thread. Ma anche se Rails lo utilizza, non hai alcun controllo su ciò che l'app Rails sta facendo. Ad esempio, il meccanismo di benchmarking "silenzierà" il registratore commutando i livelli.

Eviterei di utilizzare il registratore di binari. Se si desidera utilizzare i thread, creare un nuovo logger all'interno del thread che registra i messaggi per tale operazione. Se non si desidera creare un nuovo registro per ogni thread, è anche possibile provare a creare un oggetto di log sicuro per il thread nel runtime a cui possono accedere ciascuno dei thread.

Al posto mio probabilmente darei un'altra occhiata alle soluzioni di lavoro in background. Mentre DRb sembra un incubo, "bj" sembra carino e facile; anche se ha richiesto un po 'di lavoro per farlo funzionare con JRuby. C'è anche l'alternativa per usare uno schedulatore Java da JRuby, vedi http://www.jkraemer.net/2008/1/12/job-scheduling-with-jruby-and-rails

+0

Grazie per le informazioni e i suggerimenti, ma a questo punto seguirò l'approccio del threading poiché funziona bene tranne che per la registrazione. Non sto usando gemme/plugin discutibili in nessuno dei thread e sto attento all'uso dei mutex per prevenire le condizioni di gara. Il mio interesse per l'utilizzo del registratore di Rails era solo la facilità di eseguire il debug e sono riuscito ad aggirarlo utilizzando i thread solo se JRUBY_VERSION è stato definito e in caso contrario è stato eseguito lo stesso codice in sequenza. Grazie comunque! –