Progettazione di applicazioni web per l'elaborazione di file ad alte prestazioni

6

Sto provando a progettare un'app Web con capacità di scalabilità, ma non riesco a spiegarmi alcuni concetti. Voglio progettarlo correttamente ma non sono un programmatore esperto, ho più esperienza di ingegneria di sistema.

L'architettura di base ha questo aspetto:

Server Web - > Server di elaborazione file - > NoSQL DB - > Cerca server

Quindi lo scenario principale è il seguente:

  • L'utente carica un file tramite il sito
  • Il file viene inviato per l'elaborazione su un server (script python)
  • I risultati dell'elaborazione vengono inviati al DB NoSQL
  • Risultati elaborati dal server di ricerca e restituiti all'utente

Possiamo scalare i frontend in web tramite il bilanciamento del carico. Qualcosa come nginx + apache.
Il ridimensionamento del database si sta prendendo cura di Cassandra o MongoDB. Il ridimensionamento della ricerca si sta prendendo cura di elasticsearch o sphinx clustering.

Ora voglio essere in grado di aggiungere più server di elaborazione file nel caso in cui il file caricato sia troppo grande. Quindi ho bisogno di dividere in qualche modo il file in blocchi e processarlo simultaneamente su più nodi più se il nodo si interrompe mentre funziona non dovrebbe influenzare nulla e i dati devono essere salvati. Quindi ho bisogno di qualcos'altro che assegnerà compiti ai miei server di elaborazione file, bilanciamento del carico e controllo dell'esecuzione delle attività.

Come progettare applicazioni personalizzate per quel tipo di cose? Dovrei usare la coda dei messaggi?

    
posta Coolface 27.03.2014 - 18:19
fonte

4 risposte

1

Al giorno d'oggi il potere del computer è economico. Inoltre, non sai ancora dove sarà il collo di bottiglia.

Per me, questo ha un odore di ottimizzazione prematura in cui ti preoccupi delle prestazioni prima ancora di avere il carico. Forse dovresti iniziare a farlo funzionare, quindi a ridimensionarlo. I miei 2 centesimi.

La domanda è anche se si desidera un tempo di elaborazione veloce o un throughput elevato. Se l'elaborazione è veramente intensiva in termini di risorse / tempo, ha senso dividere il file, distribuirlo e unire i risultati. Tuttavia, questi naturalmente arrivano ad un certo costo: divisione, invio, programmazione degli output, unione, gestione dei guasti delle parti. Questi strumenti consumano anche risorse e aggiungono molta complessità. Il calcolo distribuito è adatto solo per compiti appropriati. Il calcolo di una singola attività per server è talvolta più efficiente rispetto a tutto questo.

    
risposta data 03.11.2014 - 11:27
fonte
1

Penso che l'accodamento dei messaggi sia la tua risposta, oltre a scartare l'idea che l'utente debba attendere il completamento dell'elaborazione. Quando l'utente carica il file, lo accoda a un "processore" di messaggio che eseguirà l'analisi preliminare su di esso (in pratica basta decidere se è troppo grande e deviarlo su una coda di "splitter" o semplicemente metterlo nella normale coda di elaborazione ). A questo punto, dovresti restituire un token o un URL all'utente che possono utilizzare per accedere al risultato quando l'elaborazione è completa. In questo modo non devi preoccuparti di timeout o mantenere attiva una sessione e l'utente ha un riferimento nel caso in cui desideri / necessiti di visualizzare nuovamente i risultati senza rielaborare il file.

    
risposta data 03.11.2014 - 16:17
fonte
0

Non sono sicuro di seguire esattamente quello che stai facendo (come cosa "il file viene inviato per l'elaborazione" "mean - processing? ). Forse non è poi così importante per il contesto.

Credo che il mio primo istinto sarebbe quello di chiedere perché la tua "elaborazione" non può accadere sul tuo server delle applicazioni (come parte del processo di caricamento). Quindi, qualunque soluzione di scaling usi per il tuo server delle app, la tua "elaborazione" si ridimensiona con essa.

Tuttavia, ho anche il sospetto che forse stai cercando di progettare una soluzione altamente scalabile, con sottosistemi sintonizzabili in modo indipendente, quindi probabilmente non stai cercando di collegare il tuo server delle app al tuo evento di "elaborazione". In tal caso, ci sono diversi modi per andare.

Ho già utilizzato l'accodamento dei messaggi (come suggerito) per questo tipo di problema. Quindi, si attivano altri ascoltatori man mano che il carico aumenta. Bisogna stare attenti a quale meccanismo di attivazione si utilizza, e si deve gestire l'elaborazione delle transazioni in modo appropriato (syncpoint / rollback e commit), altrimenti l'accodamento può diventare un disastro per il debug. Sembra banale, ma nella mia esperienza, non lo è. Quando tutto funziona, è grandioso, ma devi davvero testare gli scenari dei giorni nuvolosi per assicurarti di non ricevere messaggi o messaggi scartati più di una volta. "La consegna garantita" non è tutto esaurito.

Ho anche recentemente risolto un problema come questo utilizzando una griglia di dati di memoria condivisa (Hazelcast). L'API implementa effettivamente una coda per te, quindi non hai tutto il sovraccarico di configurare un gestore code come faresti con la soluzione di cui sopra. Nel mio caso avevo bisogno di eseguire un processo di trasformazione su centinaia di miliardi di righe di dati da una tabella, e scrivendo un'app multithread che girava i lettori di tabelle in diversi punti della tabella, ho buttato i record nella griglia di dati, e ho scritto un processo separato che ho potuto istanziare il numero di volte necessario per trasformare i dati, quindi è stato ridimensionato per quanto mi serviva. Suppongo che sia solo una variazione della soluzione di cui sopra. Ho eseguito un processo che impiegava circa 3 giorni per essere eseguito nell'approccio originale, a circa 15 minuti, ma era distribuito su un cluster a 50 nodi per quei 15 minuti.

    
risposta data 17.04.2014 - 03:10
fonte
0

Dovrai usare ajax (o qualche callback async o un gestore ) per colpire il server solo quando hai l'intero file, in questo modo non lo farai bisogno di dividere il file in blocchi. Dì solo all'utente che il suo file verrà elaborato e mandagli un messaggio quando è finito.

Da lì, puoi avere un metodo di lavoro asincrono (sul server) per ogni file caricato per inviarlo allo script python per l'elaborazione.

    
risposta data 09.05.2014 - 00:26
fonte

Leggi altre domande sui tag