Il diesel dovrebbe essere eseguito usando un attore di sincronizzazione, actix_web :: web :: block o futures-cpupool?


10

sfondo

Sto lavorando a un'applicazione actix-web che utilizza diesel tramite r2d2 e non sono sicuro di come effettuare query asincrone al meglio. Ho trovato tre opzioni che sembrano ragionevoli, ma non sono sicuro di quale sia la migliore.

Soluzioni potenziali

Sync Actor

Per prima cosa potrei usare l'esempio actix , ma è abbastanza complicato e richiede una buona dose di boilerplate per essere costruito. Spero che esista una soluzione più ragionevole.

Actix_web::web::block

Come altra opzione potrei usare il actix_web::web::blockper avvolgere le mie funzioni di query in un futuro, ma non sono sicuro delle implicazioni sulle prestazioni di questo.

La query è quindi in esecuzione nello stesso sistema Tokio? Da quello che ho potuto trovare nella fonte, crea un thread nel threadpool actix-web sottostante . È un problema?

Se leggo bene il codice, r2d2 blocca il suo thread quando acquisisce una connessione, che bloccherebbe parte del pool actix-web core. Lo stesso con le query del database. Questo bloccherebbe quindi tutto actix-web se faccio più query di quante ne abbia thread in quel pool? Se è così, grosso problema.

Futures-cpupool

Infine, la scommessa sicura che può avere alcune spese generali non necessarie è futures-cpupool . Il problema principale è che questo significa aggiungere un'altra cassa al mio progetto, anche se non mi piace l'idea di più pool di CPU che fluttuano inutilmente nella mia applicazione.

Poiché sia ​​la r2d2 che il diesel si bloccano, ci sono una quantità sorprendente di cose difficili qui.

Soprattutto, non condividere questo cpupool con qualcosa che non utilizza lo stesso pool r2d2 (poiché tutti i thread creati potrebbero bloccare l'attesa di una connessione r2d2, bloccando l'intero pool quando esiste lavoro).

In secondo luogo (un po 'più ovviamente), quindi non dovresti avere più connessioni r2d2 rispetto ai thread nel pool e viceversa poiché quella più grande sprecherebbe risorse (connessioni non utilizzate / thread costantemente bloccati) (forse un altro thread, forse più veloce passaggio di connessione dallo scheduler del sistema operativo anziché dallo scheduler cpupool).

Infine, ricorda quale database stai utilizzando e le prestazioni che hai lì. Eseguire una singola connessione r2d2 e un singolo thread nel pool potrebbe essere la cosa migliore in un'applicazione sqlite pesante di scrittura (anche se consiglierei un database adeguato per tale).

Vecchie risposte

Vecchie soluzioni che potrebbero funzionare

https://www.reddit.com/r/rust/comments/axy0hp/patterns_to_scale_actixweb_and_diesel/

In sostanza, raccomanda Futures-cpupool.

Qual è l'approccio migliore per incapsulare l'I / O di blocco in future-rs?

Raccomanda Futures-cpupool per casi generali.

Vecchie soluzioni che non funzionano

https://www.reddit.com/r/rust/comments/9fe1ye/noob_here_can_we_talk_about_async_and_databases/

Una soluzione davvero piacevole per una vecchia versione di actix-web. Da quello che posso trovare le richieste non contengono più un pool di CPU.


Dai commenti in questo numero , sembra che futures-cpupoolsia la soluzione alternativa raccomandata per la mancanza di asyncsupporto in Diesel.
Jmb,

Questa è più una soluzione generale. Spero in qualcosa che possa sfruttare il sistema actix. Tuttavia, ora cercherò in futures-cpupool per cercare problemi.
Logina,

Benvenuto in Stack Overflow! Sembra che alla tua domanda potrebbe essere data una risposta dalle risposte Qual è l'approccio migliore per incapsulare l'I / O di blocco in future-rs? . In caso contrario, modifica la domanda per spiegare le differenze. Altrimenti, possiamo contrassegnare questa domanda come già risposta.
Shepmaster

Dato che cpupool interagisce anche con il pool di connessioni bloccanti in r2d2, non sono sicuro di come risolverlo al meglio. Lo sto esaminando io stesso ora e lo aggiornerò presto.
logina,

Risposte:


3

Vado con futures-cpupool. È la soluzione migliore a causa della natura bloccante delle mie interazioni.

L'uso di actix_web :: web :: block è abbastanza decente, ma utilizzerà un pool di thread condiviso in actix (e a causa delle chiamate di blocco che uso, questo può bloccare l'intero pool di thread e interferire con altre attività assegnate a actix_web).

È meglio usare futures-cpupool per creare un threadpool separato per database solo per le interazioni con il database. In questo modo si raggruppano tutte le attività che devono attendere reciprocamente (quando sono presenti più attività rispetto alle connessioni) in un pool, impedendo loro di bloccare qualsiasi altra attività che non necessita di una connessione e limitando potenzialmente il numero di thread al numero di connessioni (in modo che l'attività venga pianificata solo quando non verrà bloccata).

Nel caso in cui desideri utilizzare solo una connessione al database (o pochissime) l'attore di sincronizzazione è un'opzione abbastanza buona. Funzionerà come una futures-cpupool con un thread, assicurando che tutte le attività vengano eseguite una alla volta, tranne per il fatto che utilizzerà uno dei thread sottostanti di actix-web piuttosto che uno separato (quindi, buono solo per pochissime connessioni) . Trovo la piastra della caldaia troppo grande per valerne la pena, però.


6
leggendo i miei risultati sopra - si prega di inserire le informazioni pertinenti alla risposta nella risposta , non alla domanda.
Shepmaster
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.