Mvc 5, îmbunătățiri de performanță cu controlori

ASP.NET --- ASP.NET MVC 5 --- Îmbunătățirea performanței cu ajutorul controlorilor

MVC Framework oferă două tipuri speciale de controlere care pot îmbunătăți performanța aplicațiilor Web MVC în curs de dezvoltare. Ca și în cazul oricărei optimizări a performanței, lucrul cu aceste controlere fie va sacrifica ușurința utilizării, fie va face față unor funcționalități limitate. Următoarele secțiuni vor demonstra folosirea ambelor tipuri de controlere și vor explica avantajele și dezavantajele asociate acestora.







Utilizarea controlorilor care nu acceptă starea sesiunii

Implicit, controlorii mențin o stare de sesiune care poate fi utilizată pentru a stoca valorile datelor între solicitări, facilitând astfel programatorilor MVC să rezolve problemele. Crearea și menținerea stării sesiunii este un proces complex. Datele trebuie stocate și preluate, iar sesiunile trebuie să fie gestionate astfel încât să asigure o politică adecvată a uzurii. Datele din sesiune consumă memorie pe server sau într-un alt spațiu de stocare, iar nevoia de sincronizare a datelor între mai multe servere web îngreunează rularea aplicației pe mai multe servere (pentru aplicații mari).

Pentru a simplifica menținerea stării sesiunii, ASP.NET va procesa o singură cerere pentru o anumită sesiune la un moment dat. În cazul în care clientul emite o mulțime de solicitări care se suprapun, serverul le va coaliza și le va procesa secvențial. Avantajul acestei abordări este că nu trebuie să vă faceți griji cu privire la modificarea acelorași date cu multe solicitări în același timp. Dezavantajul este legat de imposibilitatea de a atinge cantitatea necesară de solicitări.

Nu toți controlorii au nevoie de o facilitate de stare a sesiunii. În astfel de cazuri, performanța aplicației poate fi îmbunătățită prin evitarea lucrului asociat cu menținerea stării sesiunii. Acest lucru se realizează prin utilizarea controlorilor care nu acceptă starea sesiunii. Ele sunt foarte asemănătoare cu controlorii convenționali, dar cu două excepții: MVC Framework nu va încărca sau stoca starea sesiunii atunci când astfel de controlere sunt folosite pentru a procesa cererea, iar cererile care se suprapun pot fi tratate simultan.

Gestionarea stadiului sesiunii într-o fabrica speciala IControllerFactory

În discutarea controlerele de plante într-un articol anterior, am arătat că interfața IControllerFactory conține o metodă numită GetControllerSessionBehavior (). care returnează valoarea enumerării SessionStateBehavior. Această enumerare conține patru valori care controlează configurația stării sesiunii în controler:

Valorile enumerării SessionStateBehavior

Starea sesiunii este complet dezactivată

Fabrica de controler care implementează interfața IControllerFactory stabilește direct comportamentul de stare a sesiunii pentru controlorii, returnând valorile SessionStateBehavior din metoda GetControllerSessionBehavior (). Această metodă ia ca parametri obiectul RequestContext și un șir care conține numele controlerului. Puteți să returnați oricare dintre cele patru valori descrise în tabelul de mai sus și diferite controluri pot reveni la diferite valori.

Următorul exemplu prezintă o implementare modificată a metodei GetControllerSessionBehavior () din clasa CustomControllerFactory creată mai devreme:

Gestionarea stării unei sesiuni utilizând DefaultControllerFactory

Dacă utilizați fabrica de controler încorporată, puteți controla starea sesiunii de controler prin aplicarea atributului SessionState la clasele individuale de controler, așa cum se arată în exemplul de mai jos, unde a fost creat un nou controler numit FastController:

Atributul SessionState este aplicat clasei de controler și afectează toate metodele de acțiune din acest controler. Singurul parametru acceptat de acest atribut este valoarea enumerării SessionStateBehavior. În exemplul de mai sus, starea sesiunii este complet dezactivată. Aceasta înseamnă că dacă încercați să setați valoarea sesiunii în controler, de exemplu:

sau încercați să le citiți în vizualizare:

MVC Framework va arunca o excepție atunci când acțiunea este chemată sau vizualizarea este redată. Când starea sesiunii este dezactivată, proprietatea HttpContext.Session revine null.

Utilizarea controlorilor asincroni

Bazându-se pe cadrul MVC, ASP.NET acceptă piscina thread .NET. care este folosit pentru a procesa cererile clientului. Această grupare se numește bazinul firului lucrător, iar toate firele sunt, respectiv, fire de lucru. Când se primește o solicitare, firul lucrătorului este preluat din bazin și începe să proceseze cererea. După procesarea solicitării, fluxul de lucru este returnat la piscină, astfel încât acesta să fie disponibil pentru procesarea de noi cereri în momentul în care ajung.

Aplicarea unei baze de fire în aplicațiile ASP.NET oferă două avantaje:

Prin reutilizarea fluxurilor de lucru, puteți evita cheltuielile aferente creării unui nou flux de lucru de fiecare dată când trebuie să procesați o solicitare.

Datorită prezenței unui număr fix de fluxuri de lucru disponibile, este posibilă evitarea situației în care numărul cererilor procesate simultan depășește capacitățile serverului.







Piscina fluxului de activități funcționează mai bine atunci când cererile pot fi procesate într-o perioadă scurtă de timp. Această situație este tipică pentru majoritatea aplicațiilor MVC. Cu toate acestea, în prezența unor acțiuni care depind de alte servere, și necesită o lungă perioadă de timp pentru a finaliza, este posibil ca toate firele lucrător sunt ocupate de așteptare pentru finalizarea altor sisteme.

Serverul este capabil să facă mai mult de lucru (la urma urmei, foarte puține resurse sunt necesare în timpul așteptării), dar deoarece toate fluxurile de lucru sunt conectate, cererile de intrare sunt în coada de așteptare. Există o situație destul de ciudată atunci când aplicația pare să se hrănească, în timp ce serverul este în cea mai mare parte inactiv.

În acest moment, este posibil să aveți ideea implementării proprii a fluxului de fluxuri de lucru, care este configurat precis pentru o anumită aplicație. Nu face asta în nici un fel! Scrierea codului paralel este destul de simplă. Cu toate acestea, scrierea unui cod paralel de lucru este dificilă, mai ales pentru începători în programarea paralelă. Se recomandă aderarea la piscina standard. Dacă aveți experiență în programarea paralelă, trebuie să fiți conștient de faptul că beneficiile vor fi foarte mici în comparație cu eforturile de codificare și testare a unui nou fond de fire.

Deci, soluția la această problemă este utilizarea unui controler asincron. Aceasta va crește performanța generală a aplicației, dar nu va oferi niciun avantaj pentru efectuarea operațiilor asincrone.

Controlerele asincrone sunt utile doar pentru acțiunile care implică un I / O sau o rețea, dar nu acelea pe care CPU le utilizează intens. Problema pe care încercați să o rezolvați cu ajutorul controlorilor asincroni este legată de nepotrivirea dintre modelul bazinului de date și tipul de cereri care sunt procesate. Bazinul este conceput pentru a se asigura că fiecare cerere primește o parte corespunzătoare a resurselor serverului, dar în final un set de fluxuri de lucru care nu fac nimic. Dacă aplicați flux de fundal suplimentar pentru activități intensive cu CPU, resursele serverului vor fi irosite în prea multe cereri simultane.

Această secțiune presupune că sunteți familiarizat cu Biblioteca paralelă de activități (TPL). Biblioteca în sine este descrisă în secțiunea Threads and Files. De asemenea, puteți vedea un exemplu de creare a unui formular web asincron pe formularul Web ASP.NET.

Exemplu de preparare

Înainte de a începe să explicăm controlerele asincrone, vom demonstra un exemplu de problemă pentru care sunt destinate. Exemplul de mai jos arată codul unui controler sincron convențional denumit RemoteData, care a fost adăugat la proba de proiect:

Acest controler conține o metodă de acțiune numită Data () care creează o instanță a clasei modelului RemoteService și apelează metoda GetRemoteData () pe ea. Această metodă este un exemplu de acțiune care durează mult timp, dar utilizează puțin procesor. Exemplul de mai jos arată clasa RemoteService definită în fișierul RemoteService.cs din dosarul Modele:

De fapt, metoda GetRemoteData () este simulată aici. În realitate, această metodă ar putea extrage date complexe printr-o conexiune de rețea lentă, dar pentru simplitate am folosit metoda Thread.Sleep () pentru a emula o întârziere de două secunde. Ultima adăugare este noua vizualizare. Pentru a face acest lucru, dosarul Views / RemoteData este creat în care fișierul de vizualizare Data.cshtml este plasat împreună cu conținutul prezentat în exemplu:

După pornirea aplicației și du-te pentru a forma URL / RemoteData / apeluri date metoda adecvată etapele obiect RemoteService este creat și apoi invocat GetRemoteData) metoda (. După două secunde (simulând funcționarea efectivă de performanță) care se întorc de date de la GetRemoteData (), care sunt transmise reprezentarea pentru vizualizare:

Mvc 5, îmbunătățiri de performanță cu controlori

Problema constă în faptul că firul lucrător care se ocupă de cererea, mers în gol timp de două secunde - el nu a făcut nimic util, și nu era disponibilă să se ocupe de alte cereri, în timp ce aștepta.

Crearea unui controler asincron

Prin utilizarea unui controler asincron, fluxul de lucru este eliberat și poate face față altor solicitări. Nu împiedică utilizatorul să interacționeze cu interfața aplicației timp de două secunde. În final, datele fictive vor fi primite și procesate. Există tehnologii bazate pe client (AJAX), cu ajutorul cărora puteți face astfel de solicitări în browser, ceea ce permite cel puțin să informeze utilizatorul despre evoluția achiziției de date și să îi ofere posibilitatea de a continua lucrul cu o altă parte a aplicației.

După ce vom ilustra problema pe care o vom rezolva, să trecem la crearea unui controler asincron. Un astfel de controler poate fi creat în două moduri. Prima este implementarea interfeței IAsyncController a spațiului de nume System.Web.Mvc.Async, care este echivalentul asincron al IController. Această abordare nu va fi demonstrată, deoarece necesită o explicație detaliată a conceptelor de programare paralelă .NET.

În continuare se va concentra atenția asupra Cadrului MVC, astfel încât exemplul celei de-a doua abordări să fie următorul: utilizarea noilor cuvinte-cheie așteaptă și asincronizarea într-un controler convențional.

În versiunile anterioare ale .NET Framework, crearea de controlere asincrone a fost o sarcină consumatoare de timp și a impus ca controlorul să moștenească de la o clasă specială și să împartă fiecare acțiune în două metode. Cuvintele cheie noi așteaptă și async face acest proces mult mai ușor: trebuie să creați un nou obiect Task și să aplicați așteptați rezultatul, așa cum se arată în exemplul de mai jos:

Vechea modalitate de a crea metode de acțiune asincrone este încă susținută, deși abordarea luată în considerare aici este mult mai elegantă, deci este recomandată utilizarea acesteia. Unul dintre artefactele abordării vechi este imposibilitatea de a aplica nume pentru metodele din domeniul de nume care se termină în Async (de exemplu, IndexAsync ()) sau Completed (say, IndexCompleted ()).

Deci, în acest exemplu, metoda de acțiune a fost refactată, așa că revine acum sarcina. se aplică asincron și așteptați cuvintele cheie și obiectul Task, care este responsabil pentru a apela metoda GetRemoteData ().

Utilizarea metodelor asincrone în controler

Un controler asincron poate fi, de asemenea, utilizat pentru a utiliza metode asincrone în altă parte a aplicației. În scopuri demonstrative, metoda asincronă este adăugată la clasa RemoteService, după cum se arată în exemplul de mai jos:

Rezultatul metodei GetRemoteDataAsync () este obiectul Task, care produce același mesaj ca și metoda sincronă când este terminată. În exemplul de mai jos, puteți vedea modul în care se utilizează această metodă asincronă în noua metodă de acțiune adăugată la controlerul RemoteData:

După cum puteți vedea, ambele metode de acțiuni urmează același model de bază, iar diferența apare numai acolo unde este creat obiectul Task. Ca urmare a apelării oricărei metode de acțiune, firul lucrătorului nu va fi legat în așteptarea finalizării apelului GetRemoteData (). Aceasta înseamnă că firul este disponibil pentru a face față altor cereri, îmbunătățind astfel foarte mult indicatorii de performanță ai aplicației MVC Framework.







Trimiteți-le prietenilor: