Jedna z mojich obľúbených otázok na pohovore je „Čo vám hovoria slová ako async a wait ?“ pretože to otvára príležitosť na zaujímavú diskusiu s opýtaným... Alebo nie, pretože sa vznášajú na túto tému. Podľa môjho názoru je veľmi dôležité pochopiť, prečo používame túto techniku.
Mám pocit, že mnohí vývojári sa radšej spoliehajú na vyhlásenie „je to najlepší postup“ a slepo používajú asynchrónne metódy.
Tento článok ukazuje rozdiel medzi asynchrónnymi a synchrónnymi metódami v praxi.
Spustím benchmark nasledujúcim spôsobom. Na dvoch počítačoch bežia dve nezávislé inštancie kobyliek. Inštancie Locustu simulujú používateľa, ktorý robí nasledovné:
Pod kapotou sa každá App Service pripojí k svojej vlastnej databáze a vykoná SELECT dotaz, ktorý trvá päť sekúnd a vráti niekoľko riadkov údajov. Odkazy nájdete v kóde ovládača nižšie. Použijem Dapper na zavolanie do databázy. Chcel by som upriamiť vašu pozornosť na skutočnosť, že asynchrónny koncový bod volá databázu asynchrónne ( QueryAsync<T> ).
Stojí za to dodať, že nasadzujem rovnaký kód do oboch služieb aplikácie.
Počas testu sa počet používateľov rovnomerne rozrastie na cieľové číslo ( Počet používateľov ). Rýchlosť rastu je riadená parametrom Spawn Rate (počet jedinečných používateľov, ktorí sa môžu pripojiť za sekundu) – čím vyššie číslo, tým rýchlejšie sa používatelia pridávajú. Rýchlosť spúšťania je nastavená na 10 používateľov/s pre všetky experimenty.
Všetky experimenty sú obmedzené na 15 minút.
Podrobnosti o konfigurácii stroja nájdete v časti Technické podrobnosti v článku.
Červené čiary odkazujú na asynchrónne a modré čiary na synchrónny koncový bod.
To je o teórii. Začnime.
Vidíme, že oba koncové body fungujú podobne – spracovávajú približne 750 požiadaviek za minútu so strednou dobou odozvy 5200 ms.
Najfascinujúcejším grafom v tomto experimente je trend vlákna. Môžete vidieť výrazne vyššie čísla pre synchrónny koncový bod (modrý graf) – viac ako 100 vlákien!
To sa však očakáva a zodpovedá to teórii – keď príde požiadavka a aplikácia zavolá do databázy, vlákno sa zablokuje, pretože musí čakať na dokončenie spiatočnej cesty. Preto, keď príde ďalšia požiadavka, aplikácia musí vytvoriť nové vlákno, aby ju zvládla.
Červený graf – počet vlákien asynchrónneho koncového bodu – dokazuje odlišné správanie. Keď príde požiadavka a aplikácia zavolá do databázy, vlákno sa namiesto zablokovania vráti do oblasti vlákien. Preto, keď príde ďalšia požiadavka, toto bezplatné vlákno sa znova použije. Napriek narastajúcemu počtu prichádzajúcich požiadaviek aplikácia nevyžaduje žiadne nové vlákna, takže ich počet zostáva rovnaký.
Za zmienku stojí 3. metrika – stredná doba odozvy . Oba koncové body ukázali rovnaký výsledok – 5200 ms. Z hľadiska výkonu teda nie je žiadny rozdiel.
Teraz je čas zdvihnúť stávky.
Záťaž sme zdvojnásobili. Asynchrónny koncový bod túto úlohu úspešne zvláda – rýchlosť jeho požiadaviek za minútu sa pohybuje okolo 1500. Synchrónny brat nakoniec dosiahol porovnateľné číslo 1410. Ak sa však pozriete na graf nižšie, uvidíte, že to trvalo 10 minút!
Dôvodom je, že synchrónny koncový bod reaguje na príchod nového používateľa vytvorením ďalšieho vlákna, ale používatelia sú pridávaní do systému (len pre pripomenutie, že rýchlosť spúšťania je 10 používateľov/s) rýchlejšie, než sa dokáže prispôsobiť webový server. Preto hneď na začiatku stálo v rade toľko žiadostí.
Nie je prekvapením, že metrika počtu vlákien je stále okolo 34 pre asynchrónny koncový bod, zatiaľ čo sa zvýšila zo 102 na 155 pre synchrónny koncový bod. Stredný čas odozvy sa znížil podobne ako rýchlosť požiadavky za minútu – čas synchrónnej odozvy bol na začiatku experimentu oveľa vyšší. Ak by som test nechal 24 hodín, stredné čísla by boli párne.
Tretí experiment je určený na preukázanie trendov odhalených počas druhého – môžeme vidieť ďalšiu degradáciu synchrónneho koncového bodu.
Používanie asynchrónnych operácií namiesto synchrónnych operácií priamo nezlepšuje výkon ani používateľskú skúsenosť. Po prvé, zvyšuje stabilitu a predvídateľnosť pod tlakom. Inými slovami, zvyšuje prah zaťaženia, takže systém môže spracovať viac, než dôjde k degradácii.
Na dosiahnutie najčistejšieho výsledku testu by som mal spustiť testy z 2 virtuálnych počítačov umiestnených v rovnakej sieti, v ktorej sa nachádzajú cieľové služby aplikácií.
Predpokladal som však, že oneskorenie siete ovplyvní obe aplikácie viac-menej podobným spôsobom. Preto nemôže ohroziť hlavný cieľ — porovnanie toho, ako sa správajú asynchrónne a synchrónne metódy.
Čo som hackol, aby som prinútil synchrónny koncový bod vykonávať takmer rovnako asynchrónne a vykreslil graf nižšie (podmienky experimentu sú rovnaké ako v treťom – 200 používateľov)?