ASP.NET autentikáció: nem bírja a farka?

Azt játszom a Microsofttal, hogy az Azure-ban szándékosan, és lehetőleg a legvégsőkig a legkisebb szerverpéldánnyal futtatom a weblapunkat. Small instance, egyetlenegy proci, 2 GB ram, amíg bírja. Ez a kis konfiguráció szolgálja ki az itfactory.hu-t és a netacademia.net, .hu-t is. Pörgősen teszi, bírja akár a többszáz fős tanfolyamokat is. Erre pedig azért képes, mert kesselünk, mint az ördög, az SQL Servert – ha lehet – egyáltalán nem kérdezzük le, és van OutputCache-rendszerünk is, fut ez, mint a villám. Sőt, olyan gyorsan fut, hogy csak kapkodom a fejem. (Korábban azt hittem, ez a teljesítmény MS-platformon egyáltalán nem lehetséges, mert amilyen lassú mondjuk maga az Azure.com, meg a LiveID-bejelentkezés (mondjuk ki: szánalmas), arra a téves következtetésre jutottam, hogy nagy teljesítményű, friss, gyorsan válaszoló webalkalmazást nem is lehet ezzel a felálással készíteni. De lehet, csak kesselni kell, mint az ördög és az SQL Server folyamatos szólongatását hanyagolni kell.

Szóval szépen megy minden, fillérekért. Mégis, valahányszor nyílt napot hirdetünk, mindig letérdel az egész, nem tudok mást tenni, mint hirtelen a Scale Up funkcióhoz nyúlni, hozzácsapni még 6-8 szervert, amíg az esemény tart. Ez egy bosszantó és zsebmetsző dolog, ezért úgy döntöttem, kimérem, miért pont a nyílt napokon térdel le rendszeresen?

Elsőként különböző http-teszteket futtattunk, aminek a részleteivel nem untatnám a Tisztelt Érdeklődőket, hisz ez egy SQL-blog, hanem rögtön a végeredményhez ugrok: az autentikáció miatt borul össze. Az pedig azért van, mert a logint nem lehet bekesselni. Minden mást nagyjából igen, de bejelentkezéskor mindenképpen az SQL Serverhez kell fordulni, hogy létezik-e Gipsz Jakab, ezzel és ezzel a jelszóval?

Kezdjük azzal, hogy az ASP.NET Forms autentikáció alaptábláin nincs egy darab index sem. Ami nem is baj addig, amíg az embernek 4-5 júzere van. Na hát ez nálunk egy picit magasabb szám, a százezret verdesi alulról. Ilyen mennyiségű rekordszámon a sima Table Scan azért eltart egy darabig. Konkrétan a rendszerünk jelenleg másodpercenként fél logint tud megcsinálni Smile

És már meg is van, miért válik elérhetetlenné egy-egy nyílt napon: ilyenkor szite egyidőben szeretne bejelentkezni 600-800 fő. Mindegyik olyan 2-2 másodpercre kiakasztja a procit. A teljes létszám bejelentkeztetése 1600 másodpercbe telne, ha csak ez az egy folyamat futna. Na de ez enm így van, hisz a loginon felül weblapot is kellene adni, meg SilverLight klienst meg kukit meg mittudomén miket. Ebből már látszik is, hogy fél órára simán kiakad az egész hóblebanc.

Oldjuk meg a feladatot!

Első kísérletképpen tettem egy indexet a Users tábla Username mezőjére, mondván hogy a bejelentkezéskor erre keresünk rá.

create index usernameindex on users(username)

Remek. A gyorsulásunk azonban kerek 0% lett! Valami miatt a rendszer nem használja a szuperjó indexemet. Biztos azért nem csináltak “gyárilag”, mert tudták, hogy felesleges Surprised smile

Nincs mit tenni, ki kell mérni, mit is futtat az MVC, amikor bejelentkezünk. Nosza, elő egy SQL Profilert! (Ez persze nem ilyen egyszerű, Azúrban lévő SQL-adatbázisról lévén szó. Itt lerövidítve közlöm a történetet.)

Ez itt a bejelentkezés első lekérdezése (kigyomláltam a lényegtelen részeket):

select * from users where lower(UserName)='asdasd'

És már meg is találtuk, miért nem használja az indexemet! Hát azért, mert az ügyes redmondi fiúk ennek elejét vették azzal, hogy a WHERE-feltételben a mezőm értékét kisbetűsítik. Ha nem lenne ott az a lower(), rögtön indexhez nyúlna, és körülbelül harmincszor gyorsabban futna le. Íme a bizonyíték (mindkér változat végrehajtási tervét egyszerre kértem le, CTRL+L):

image

Nos, ez most már megvan, de vajon hogyan lehetne rávenni a Membership providert, hogy ne csinálja ezt a balfékséget (lower()), és ne vegyen ki a zsebemből egy csomó pénzt?

Újra kellene írni az egészet, azt hiszem Sad smile Mert ha már hozzányúlok, akkor ezt is kesselni kellene (mint az ördög!), mert például most vettem észre, hogy bizonyos lekérdezéseket duplán futtat le. Arról nem is beszélve, hogy minden bejelentkezésnél felülírja a LastLoginDate mezőt, ami egy fincsi Update utasítás bele a közepébe… ami mindig elakad persze, mert a többi Login fogja az egész táblát. Na de írjon providert, akinek nincs jobb dolga. Akkor viszont zsákutcába jutottam.

Szép kis kalamajka! Nincs valakinek egy épkézláb ötlete?


Elküldve 2014. 02. 03. 15:08 by Lecram Megtekintve: 376 alkalommal

Comments

gnagypal wrote re: ASP.NET autentikáció: nem bírja a farka?
on P, febr. 7 2014 1:21

Szia!

Esetleg meg lehet próbálni egy plusz számított mezőbe letárolni a lower(UserName) értékét, és a számított mezőre indexet készíteni.

Pl az AdventureWorks adatbázis person táblájánál:

ALTER TABLE [Person].[Person]

 ADD LowerLastName AS LOWER(LastName) PERSISTED;

CREATE NONCLUSTERED INDEX IX_LowerLastName

 ON [Person].[Person](LowerLastName);

Üdv,

G.