13

Sto costruendo un'applicazione che consente di caricare grandi quantità di caricamenti fotografici contemporaneamente, e volevo sapere quale sarebbe stata la migliore configurazione per affrontare questo problema.Migliore architettura di Ruby on Rails per Image Heavy

Questo è quello che sto usando finora:

  • Jquery di caricamento dei file: consente agli utenti di trascinare e rilasciare le immagini
  • CarrierWave: elabora le immagini e li ridimensiona con ImageMagick
  • Amazon S3: arrivi CarrierWave immagini per Amazon S3 attraverso la nebbia
  • Heroku: per l'hosting

mi piacerebbe per permettere agli utenti di essere in grado di trascinare e rilasciare una grande quantità di immagini su una pagina e quindi navigare verso altre pagine mentre il caricamento è in corso in background. Mi piacerebbe anche che le immagini appaiano quando finiscono di caricare. Non voglio che questo processo blocchi i dynos di Heroku, quindi probabilmente ho bisogno di spostare il lavoro in un lavoro in background, ma non sono sicuro di cosa usare per la mia situazione.

Qual è la migliore configurazione per questo tipo di app? Quale gemma dell'operaio di sfondo dovrei usare? Cloudinary è una buona idea?

+0

aggiungi modulo di caricamento per web-server per evitare l'utilizzo della CPU non necessario su File copia – Viren

risposta

34

Ho recentemente creato un'applicazione che accetta un numero elevato di caricamenti su Heroku. Ho deciso di costruire la mia soluzione invece di usare il cloud o un equivalente. Ecco alcune lezioni che ho imparato:

  • Non caricare su heroku. L'intero web worker verrà bloccato per l'intera durata del caricamento. Questo è fino a un minuto. Inaccettabile.

  • Utilizzare un uploader javascript (come jquery-file-upload) per caricare direttamente su s3. All'inizio è un po 'complicato, ma una volta che funziona è fantastico.Puoi utilizzare la gemma s3_direct_upload oppure puoi semplicemente leggere la loro fonte per creare la tua soluzione da zero. Quella gemma era basata su un episodio railscasts pro, che devi pagare, ma ha source available.

  • Al termine del caricamento, effettuare una richiesta Ajax alla propria applicazione passando il nuovo URL s3 come remote url. Carrierwave elaborerà quindi l'immagine su s3 come se fosse stata caricata, tranne in un paio di secondi anziché fino a un minuto.

  • Utilizzare jquery-file-upload's client-side image resizing. Qualcuno proverà a caricare una foto da 5 MB e poi la stronza che il caricamento dura per sempre. Questo renderà tutti gli upload il più velocemente possibile.

  • Configurare s3 su clear your uploads folder automatically.

  • Non utilizzare sottile. Utilizzare unicorn. Un paio di secondi è troppo lungo per elaborare una richiesta sottile, ma unicorno con tre o quattro lavoratori è molto più indulgente.

  • Non utilizzare rmagick. È un'API migliore per la manipolazione di immagini complesse ma utilizza incredibili quantità di memoria. Usa invece mini_magick.

Si noterà che non sto utilizzando un lavoratore in background per tutto questo. Se ti senti davvero meticoloso, potresti avere il controller che riceve l'URL remoto passare il lavoro a un lavoratore in background, e se hai bisogno del risultato immediatamente il lavoratore in background potrebbe notificare l'IU da pubsub (faye o pusher, possibilmente con il eccitante nuova gemma sync). Ma questo non era necessario per la mia applicazione, e preferirei spendere i miei soldi su un altro banco di prova rispetto a un addetto operaio.

E, sì, se volete lasciarli fare clic su tutta la vostra applicazione mentre sta accadendo, avrete bisogno di essere caricati in un popup (e usando una sorta di soluzione Pubub), o di costruire il vostro intero sito come un'applicazione javascript utilizzando ember o backbone o angolare o altro.

Hai qualche domanda?

+0

Ci sono problemi di reattività nel fare qualsiasi elaborazione, anche solo di pochi secondi, su un banco prova. Lo strato di bilanciamento del carico di Heroku non è più a conoscenza se ciascun banco sia effettivamente disponibile per gestire una richiesta o meno. Le richieste vengono caricate a caso in modo bilanciato su tutte le dinamiche e le richieste da altri utenti potrebbero finire per attendere il processo di richiesta di elaborazione delle immagini per 3-5 secondi, anche se un altro banco sarebbe stato in grado di gestire immediatamente la richiesta. È sempre meglio mantenere le richieste super-veloci su heroku. [Fonte articolo] (http://rapgenius.com/James-somers-herokus-ugly-secret-lyrics) –

+1

Concordato. Ecco perché heroku [ha cambiato la loro raccomandazione ufficiale] (https://blog.heroku.com/archives/2013/2/27/unicorn_rails) dal thin all'unicorno, dove il problema è molto meno pronunciato. La migliore architettura possibile coinvolge i lavoratori, ma potrebbe non essere necessaria per tutte le applicazioni e sicuramente non avrà lo stesso impatto, ad esempio, degli upload diretti di s3. – Taavo

6

Non avevo mai visto Cloudinary prima di menzionarlo, ma sembra che sarebbe perfetto per il tuo progetto.

Innanzitutto, potrebbe potenzialmente semplificare notevolmente la tua app. Supporta cloud direct uploads from the browser tramite la sua API HTTP, e c'è già un jquery plugin che si basa sul caricamento di file jQuery e ha caratteristiche simili, compresa l'elaborazione di pre-caricamento lato client.

Inoltre, supporta trasformazioni al volo simili a dragonfly (anche una molto buona libreria di distribuzione).

Ciò significa che, a meno che non sia davvero necessario caricare tali immagini tramite l'app, è possibile aggirarle completamente, caricando direttamente su Cloudify e gestendo il ritaglio delle immagini e altre trasformazioni tramite il loro transformation API.

Se lo si desidera, è possibile eliminare Carrierwave e S3 dall'app e ovviamente non è necessario alcun dynos di sfondo per gestire l'elaborazione delle immagini. Inoltre, probabilmente sarebbe molto più veloce (caricamento diretto e manipolazione immediata rispetto al caricamento sulla tua app, elaborazione e caricamento sul cloud) e eliminerebbe la larghezza di banda per il caricamento attraverso la tua app.

Anche senza upload diretto, sembra che Cloudinary fornisca un plug-in Carrierwave che potrebbe ancora utilizzare la loro API di trasformazione, ovviando alla necessità che l'app elabori le immagini.

+0

Ciò consentirebbe agli utenti di pubblicare un gruppo di foto che poi vengono caricate in background (in modo che possano lasciare la pagina senza interrompere il processo di caricamento)? –

+0

Non vedo succedere questo senza aprire una finestra popup per gestire il caricamento. Altrimenti quando lasci la pagina, interromperà il caricamento. Non conosco il background dei processi in un browser web che io conosca. – numbers1311407

+0

Tuttavia, a seconda di ciò che si sta facendo si potrebbe ancora aggiungere una sorta di componente push allo stack, come Faye o qualche implementazione WebSocket, che consente di spingere le notifiche per le immagini caricate. – numbers1311407