2010-11-12 11 views
6

Ho una funzione .NET che esegue alcuni calcoli complessi. A seconda dei parametri che vengono passati in, funzione:Consigli per la progettazione di un servizio Web a lunga esecuzione e ad uso intensivo di risorse

  • impiega da diversi minuti a diverse ore per eseguire
  • utilizza il 100% di un singolo nucleo durante la computazione
  • Richiede ovunque da 100s di MB a diversi GB di memoria
  • Scrive ovunque da diversi MB a diversi GB di dati su disco
  • potrebbe generare un'eccezione, tra cui un OutOfMemoryException

La quantità di dati da scrivere sul disco può essere prevista con precisione dalla parametrizzazione della funzione. Non esiste un modo semplice per prevedere gli altri requisiti di risorse dalla parametrizzazione delle funzioni.

ho bisogno di esporre questa funzione tramite un servizio web. Questo servizio deve essere:

  • pavimento robusto e con grazia segnalare eventuali problemi durante il calcolo
  • In grado di gestire richieste simultanee, finché ci sono risorse sufficienti per gestire la richiesta senza degrado significativo delle prestazioni, e di negare con grazia la richiesta in caso contrario.

Ho intenzione di gestire la natura di lunga durata facendo in modo che la richiesta iniziale restituisca una risorsa di stato che può essere interrogata per il progresso. Una volta completato il calcolo, questa risorsa fornirà la posizione dei dati di output, che il client può scaricare (probabilmente tramite FTP).

sono meno chiare sul modo migliore per gestire gli altri requisiti. Sto considerando una sorta di "pool di calcolo" che mantiene le istanze della calcolatrice e tiene traccia di quali sono attualmente in uso, ma non ho capito i dettagli.

Qualcuno con esperienza di situazioni simili ha qualche suggerimento? Finché la soluzione può essere eseguita su una casella di Windows, tutte le opzioni tecnologiche possono essere considerate.

+0

Sia VladV sia Steven hanno fornito risposte molto utili. Sono autorizzato a contrassegnare una sola risposta come accettata, quindi ho scelto VladV in base al numero di voti al momento di scrivere questo commento. – Akash

risposta

4

Suggerirei di dividere la domanda in due parti.

  1. Il servizio Web stesso.Funzionalità:
    • Ottenere un oggetto di lavoro da un client;
    • Trasferire questo lavoro a un servizio di backend che esegue il lavoro effettivo;
    • Segnala lo stato e il risultato;
  2. Il servizio di backend. Funzionalità:
    • Elaborare le richieste dal servizio Web;
    • Esegue il calcolo effettivo.

Le ragioni di questo disegno sono
1) è relativamente difficile da gestire il carico di lavoro in applicazione ospitata (ASP.NET) perché il server (IIS) gestirà le risorse, mentre in un separato app hai più controllo diretto;
2) il design a due livelli è più scalabile - ad esempio, in seguito è possibile spostare facilmente il back-end su un'altra macchina fisica (o su più macchine).

Il servizio Web deve essere senza stato, ad esempio, dopo che una richiesta viene accettata, l'utente recupera un ID e utilizza questo ID per eseguire il polling del servizio per il risultato.

Il server di back-end, probabilmente, deve mantenere una coda delle richieste da elaborare e una serie di thread di lavoro che li elaborano. I lavoratori devono monitorare le risorse disponibili e fare attenzione a non sovraccaricare la macchina (e, naturalmente, gestire con garbo tutte le possibili condizioni di errore).

+0

Grazie, l'idea di un servizio di back-end sembra essere la chiave. Ora ho bisogno di pensare a come isolare le istanze di calcolo in modo tale che un errore in uno non uccida l'intero servizio. – Akash

+1

È sufficiente creare un gestore eccezioni catch-all in ogni thread utilizzato per il calcolo, pertanto un thread in background non genera mai un'eccezione all'esterno. Puoi anche utilizzare AppDomain per isolare le istanze l'una dall'altra, ma non penso che abbia molto senso qui. E se ti preoccupi di esaurire la memoria virtuale, passa al sistema operativo x64. – VladV

2

Mentre si può decidere di fornire un'interfaccia web service, i servizi web sono in genere non progettati per questo tipo di processi. Quello che potresti voler fare è inoltrare la richiesta a un servizio Windows (su un computer dedicato) in grado di gestirlo. I servizi di Windows non verranno riciclati e avrai un maggiore controllo sul processo.

Circa il pool di calcolo: che cosa si può provare è creare una coda di calcolo (per esempio una tabella nel database). In questo modo è possibile avere più servizi Windows su macchine dedicate che elaborano i calcoli. Questo può consentire di scalare più facilmente.

+0

Grazie, l'idea di un servizio di back-end sembra essere la chiave. Ora ho bisogno di pensare a come isolare le istanze di calcolo in modo tale che un errore in uno non uccida l'intero servizio. – Akash

+1

Quello che puoi fare è lasciare che un servizio Windows esegua sempre un calcolo alla volta e quando un calcolo (o il servizio) fallisce, puoi segnalare quel calcolo come fallito e registrare l'errore. Quello che abbiamo fatto in caso di fallimento dipendeva dal compito in questione, ma normalmente avremmo ripianificato l'attività in modo che potesse essere ripresa di nuovo in seguito. Ovviamente devi assicurarti che le attività siano atomiche. Quando un compito è riuscito, sarebbe contrassegnato come "fatto". Gli amministratori avevano un'interfaccia utente che permetteva loro di vedere quali erano le attività pianificate, che erano in esecuzione, e che erano falliti e per quale motivo. – Steven

Problemi correlati