2012-09-28 4 views
7

Desidero effettuare una chiamata a un database che ha molti dati e potrebbe richiedere del tempo per tornare.Riproduci & Akka e thread di blocco per l'accesso al database

Ho intenzione di fare quel lavoro all'interno di una chiamata ad Akka.future (f) e di usare un Async {} per rendere la risposta quando il lavoro è finito.

Ha senso farlo, o dovrei semplicemente fare la lunga chiamata di database nel controller, senza inviare il lavoro ad Akka?

Oppure c'è un modo per fare l'accesso al database non bloccante?

risposta

1

Se la risposta viene bloccata al termine della chiamata al database, è utile renderla asincrona solo se è possibile eseguire altri lavori per assemblare la risposta durante l'esecuzione della chiamata.

L'accesso al database non bloccante potrebbe significare un paio di cose diverse: una libreria client che fornisce un'API basata sul callback, che sarebbe abbastanza simile alla soluzione futura o una che utilizza socket non bloccanti per risparmiare sull'utilizzo del thread. Suppongo che tu intenda il primo, nel qual caso penso che sarebbe funzionalmente equivalente all'utilizzo di un futuro.

+0

I blocchi di chiamata DB e non ho altro lavoro da fare per quella richiesta in arrivo. Ma lo stesso server Play poteva gestire un'altra richiesta in arrivo nel frattempo. Ma se invio il lavoro ad Akka.future (lavoro), allora è gestito dallo stesso thread che gestirà ogni nuova richiesta in arrivo, quindi non penso che faccia alcuna differenza passandolo così ad Akka. In realtà potrebbe addirittura causare un sovraccarico. Ha senso? –

+1

Sì, penso che abbia senso. Supponendo di bloccare l'IO nella chiamata al database, occuperà un thread fino a quando non sarà completo. Non so giocare molto bene, ma ciò non dovrebbe impedire a qualsiasi struttura web ragionevole di servire richieste aggiuntive. Altri thread possono essere programmati sulla CPU in attesa di pacchetti dal server DB come con qualsiasi altra app e Play dovrebbe disporre di un pool di thread disponibili. Accetta la risposta se questo ha senso. =) – spieden

2

È possibile utilizzare Akka.future(f) e fornire il proprio file di configurazione Akka per ottenere più thread per elaborare gli accessi al database. Guarda this config file per esempio.

Ma lo hai sottolineato: il vero problema è l'utilizzo di un driver di database che blocca. Non so quale DB stai usando, ma vale la pena dare un'occhiata a MongoDB con ReactiveMongo per esempio. Con ReactiveMongo tutte le operazioni di MongoDB sono perfettamente non bloccanti e asincrone. C'è una buona introduzione here. Inoltre, si occupa molto bene di Play Framework (controlla lo ReactiveMongo Play Plugin).

MODIFICA: è anche possibile selezionare "Configuring Playframework's internal Akka system" per ottimizzare il numero di thread di lavoro.

+0

Sono bloccato con MySQL ..., ma sembra che abbia anche un'API asincrona! C'è documentazione per quel file di configurazione? –

+0

Poiché questo file di configurazione è in realtà per Akka, è possibile leggere il [documento di configurazione di Akka] (http://doc.akka.io/docs/akka/2.0.3/general/configuration.html). –

+0

Ho dimenticato di menzionare questo [doc] (http://www.playframework.org/documentation/2.0.3/AkkaCore) ([configurazione del sistema Akka interno di Playframework] (http://www.playframework.org/documentation/2.0.3/AkkaCore)). –

4

Se si è costretti a utilizzare un driver di blocco per il proprio database (se per qualche motivo il driver asincrono per MySQL non funziona) si consideri l'impostazione di un pool di attori (utilizzando il routing) con un PinnedDispatcher.

Il PinnedDispatcher fornisce un thread per attore e, impostando il router, ti darà la possibilità di regolare il numero di thread strettamente responsabile della gestione delle chiamate al database. Ridimensionamento semplice. Inoltre, usando gli attori è possibile strutturare i messaggi tra attori (ad esempio un messaggio con i risultati della chiamata al database) un po 'più semplice.