ASP.net MVC classe statica e background worker

1

Ho un'app ASP.net MVC 5 che funziona perfettamente. Un mio collega ha realizzato un progetto che legge i dati dai file e ne rimbalza alcuni per produrre alcuni calcoli da visualizzare nell'applicazione web. Chiamo i suoi metodi e ottengo i dati indietro e visualizzati sullo schermo.

Come parte del suo progetto ha implementato un tipo di sistema di memorizzazione nella cache, non utilizza nessuno degli strumenti di memorizzazione nella cache in. NET, sta semplicemente tenendo alcuni dei file necessari per il calcolo dei numeri in memoria poiché questi impiegano molto tempo per caricare e sono sicuramente il collo della bottiglia.

Quindi ho bisogno di fare due cose

1) Avere un'istanza della classe all'interno del progetto in modo che utilizzi i file in memoria.

2) Imposta un processo di lavoro che viene eseguito ogni giorno alle 7:00 per caricare quei file nel memo.

Per il numero uno ho istanziato la classe del mio collega come una classe statica e questo sembra funzionare un po 'di tempo ma è inaffidabile per qualche motivo sto indovinando a causa dei timeout del pool di app, sono anche preoccupato per l'efficacia di questo e se avrò problemi con più utenti che inviano richieste concorrenti. C'è un modo migliore per raggiungere questo obiettivo? Ho esaminato varie librerie di caching .NET in modo che potessi convincere il mio collega a implementare una cache corretta, ma per ora suppongo di non poterlo chiedere. Sono un po 'confuso sul motivo per cui in MVC ogni volta che un utente invia una nuova richiesta viene istanziato un nuovo controller quindi istanziare nuovamente la classe del mio collega e perdere i file in memoria?

Per il numero 2 ho letto su webbackgrounder una libreria per ASP.net che può eseguire attività in background. Tutto quello che devo fare è mentre l'app è in esecuzione su IIS, quindi eseguire un metodo tutti i giorni alle 7 del mattino.

Aggiornamento:

Non riesco a salvare l'output perché ho bisogno di calcolare queste vlaues al volo, ci sono circa 10 diversi input nel calcolo che possono cambiare in qualsiasi numero di valori diversi.

Posso davvero mettere i file di input in un database ma questo non risolve il mio problema, non sarebbe più veloce che caricarli da file, il che richiede troppo tempo, voglio tenere questi elementi in memoria quindi l'approccio alla cache.

    
posta Simon Nicholls 25.06.2017 - 20:53
fonte

3 risposte

1

Distribuisci la libreria del collega come microservizio memorizzato nella cache

Supponendo che non puoi cambiare la libreria del tuo amico, non vuoi usare un database e vuoi mantenere un livello ragionevole di isolamento del processo, ecco il modo giusto per farlo:

  1. Scrivi un po 'di colla per esporre la libreria del tuo collega come microservizio RESTful. Se non lo hai mai fatto prima, inizia qui . Non dovrebbe richiedere più di 100 righe di codice per racchiudere una chiamata di funzione.

  2. Utilizza l'interfaccia uniforme per gestire la cache e la sua durata.

  3. Imposta il pool di applicazioni per questo servizio da riciclare alle 6:59 del mattino.

  4. Modifica il tuo sito web per utilizzare il nuovo servizio.

  5. Se il codice del tuo collega richiede molto tempo per essere eseguito, il microservizio potrebbe non essere reattivo quando gestisce la sua prima richiesta. Per far fronte a questo, è necessario "riscaldare" il servizio. Imposta warmup utilizzando l'avvio automatico di IIS ; i dettagli possono essere trovati qui .

Con questo approccio, il codice del tuo collega è completamente isolato dal tuo e la logica di caching semplicemente sfrutta funzionalità standard in IIS. Con lo schema di caching e recycle impostato correttamente, dovresti avere transizioni perfette quando il programma viene riciclato, dal momento che IIS continuerà a servire richieste in volo dalla vecchia cache mentre costruisce la nuova cache. Impostiamo la scadenza della cache esattamente alle 7:01 del mattino (invece di lasciare che il riciclo del pool di app si occupi di esso) nel caso in cui ci sia un altro nodo di rete che esamina le intestazioni della cache, ad es. un server proxy che potrebbe memorizzare nella cache la risposta se non è crittografato.

    
risposta data 26.06.2017 - 11:48
fonte
2

ASP.NET MVC (su IIS) non può essere utilizzato in modo affidabile per qualsiasi tipo di lavoro in background. Il problema è che i processi IIS vengono riciclati regolarmente e non si può mai essere certi che l'attività in background avviata verrà completata correttamente (ciò è dovuto a vari motivi inerenti al processo e all'ambiente in cui opera). Non esiste una funzionalità "fire and forget" che funzioni bene con ASP.NET MVC (o qualsiasi altra cosa che gira su IIS).

Quello che ho fatto in passato per attività temporizzate molto semplici è semplicemente creare una piccola applicazione per console che si collega al progetto principale e posizionarla sul server per l'esecuzione tramite l'Utilità di pianificazione di Windows.

Per scenari (leggermente) più complessi, scrivere un "comando" su un database, quindi eseguire un'esecuzione basata su server (in genere, una console) che esegue il polling per nuove attività da eseguire su base regolare.

Per una gestione affidabile, cerca in un sistema di code come RabbitMQ, che può disaccoppiare efficacemente il processo in background dal processo MVC.

(almeno in parte il motivo del riciclo dei processi / AppPools di IIS e il fatto che un controllore viene istanziato per ogni nuova richiesta è perché aiuta a garantire che se una richiesta "va male", non si abbassi l'intero sistema)

Ecco la prima risposta alla ricerca di "ASP.NET fire and forget": link

    
risposta data 26.06.2017 - 00:52
fonte
0

ASP.NET viene fornito con una varietà di meccanismi di memorizzazione nella cache. La soluzione migliore per questa situazione è probabilmente HttpApplicationCache . Ha una specifica classe per il monitoraggio di file flat e il mantenimento della cache fino ad oggi.

Fondamentalmente si imposta una proprietà statica che avvolge la logica di memorizzazione nella cache e si utilizza la proprietà statica ogni volta che si desidera accedere al file.

static public string CachedFileContents
{
    get
    {
        ObjectCache cache = MemoryCache.Default;
        string fileContents = cache["filecontents"] as string;

        if (fileContents == null)
        {
            CacheItemPolicy policy = new CacheItemPolicy();
            policy.AbsoluteExpiration = DateTimeOffset.Now.AddHours(24);  //Set to taste

            List<string> filePaths = new List<string>();
            string cachedFilePath = Server.MapPath("~") + "\cacheText.txt";
            filePaths.Add(cachedFilePath);
            policy.ChangeMonitors.Add(new HostFileChangeMonitor(filePaths));

            // Fetch the file contents.
            fileContents = File.ReadAllText(cachedFilePath);

            cache.Set("filecontents", fileContents, policy);    
        }
        return fileContents;
    }
}
    
risposta data 26.06.2017 - 06:14
fonte

Leggi altre domande sui tag