Jag har en applikation som tillåter moduler från tredje part. Dock används samma datakälla vilket i nuläget innebär att huvudapplikationen öppnar och stänger databasen, för att sedan låta modulerna göra likadant.
Om vi säger att varje modul (plus huvudapplikationen) gör likadant minst en gång, blir antalet anslutningar i direkt proportion till antalet moduler. Det är inte bra. (En connection pool används också.)
Hur ska man bygga applikationens struktur så att man kan dra nytta av resurserna på ett bättre sätt? Hur bör man egentligen bygga?
Om det tvistar de lärde. Så länge den ligger i poolen blir det ju inte en enorm prestandahit att göra en anslutning. Alternativet är väll att låta din huvudapplikation fylla dina moduler med data, men sattsa hårt på cachning, mycket finns att spara där.
Varför ska modulerna sköta databaskopplingarna? Vore det inte enklare att modulerna bara anropade metoder som returnerade data i lämplig form och din app skötte all databashantering?
Varför ska modulerna sköta databaskopplingarna? Vore det inte enklare att modulerna bara anropade metoder som returnerade data i lämplig form och din app skötte all databashantering?
Det gör de i viss mån. Men samtidigt används modulerna för att bygga ut med ny funktionalitet, så det ligger i ämnets natur.
Däremot finns också det problemet som du nämner, att samma metoder kallas på flera olika ställen i applikationen, oberoende av varandra, och därmed blir en prestandabov.
Om vi säger att varje modul (plus huvudapplikationen) gör likadant minst en gång, blir antalet anslutningar i direkt proportion till antalet moduler. Det är inte bra. (En connection pool används också.)
Antalet anslutningar i sig är inte speciellt farligt, det är helt okej att ha 100.000 anslutningar mot databasen så länge det inte sker samtidigt.
Det viktiga är att både din APP och Modulerna håller kopplingen till databasen öppen så kort tid som möjligt. Alltså: Öppna, Hämta data, stäng. Så länge du gör det så har du gjort vad du kan.
Angående cachen så är det ett utmärkt sätt att minska anrop mot databasen, men man måste vara på det klara med att om inte ALL kommunikation till databasen går via din cache, så kommer datan i databasen och i cachen inte att stämma efter ett tag. Och det kommer bli värre problem än prestanda ;)
Säg att systemet inte är ett webbsystem, det kanske är ett system med 5.000 användare.
Skulle inte varje användare av dessa kunna ha en databasanslutning som alltid är öpppen och som dom arbetar mot, eller skulle detta vara en stor prestandaförlust?.
Som svar till Pace,
Jag tycker du skall ha något konfigurationsobjekt eller datakopplingsobjekt, som du tilldelar varje model t.ex. säg att du t.ex. har ett objekt som NHibernate's Session SÅ varje modul som du initierar så skickar du med Session:et till modulen. Alternativt du sätter denna vid uppstart till en statisk variabel (vilket kanske inte är så jättesnyggt).
Skulle inte varje användare av dessa kunna ha en databasanslutning som alltid är öpppen och som dom arbetar mot, eller skulle detta vara en stor prestandaförlust?.
Big no no, prestandahit som inte är av denna värld för sql-servern. Den frigör connections när den timar ut och skickar dem tillbaks till poolen. Scalability på en sådan lösning är ju inte speciellt bra. Det finns en connectionpool, som används med automatik från .net, det tar inte speciellt mycket kräm att hämta en connection från poolen, det är den initiala kostnaden som tar kräm, att öppna den, skicka den till poolen.
Gladh sammanfattade det bra, Alltså: Öppna, Hämta data, stäng.
Okay, vad i sql servern är det som gör att det blir segt med flera anslutningar?
Är det minne som tas upp? 5.000-10.000 användare tycker jag inte borde vara så stora problem för en av de större databaserna?
Jag vet att .NET med DataSet's har en Disconnected arkitektur, men när man arbetar med t.ex. NHibernate som jag har gjort en del nu så är den arkitekturen mer connected eftersom man måste ha den uppkopplad om man vill använda lazyload osv.
Har inget med dataset att göra, ado.net tar automatiskt hand om connectionpoolingen, om du inte explicit ber den att inte göra det.
Din connectionpooling körs ändå automatiskt även när du kör med nhibernate, den hålle rju inte anslutningen öppen bara för du kör med lazyload, den hämtar ju en connection från poolen eller skapar en ny om ingen finns i poolen först när du ber om din "lazy"-property. Slå på perfmon och kolla vad som händer med dina .net connectionobjekt, tror det är de "counters" nhibernate går på. Har kollat där själv för något år sedan :)
Inga problem med så många användare, men det blir segt med så många samtidigt öppna connections, minne mestadels.
Okay, vad i sql servern är det som gör att det blir segt med flera anslutningar?
Nu är jag ingen expert på Sql Server, så jag är nog ute och fammlar lite här. Men säg att man för att kunna hantera samtidiga anrop mot databasen, så lägger man varje öppen koppling i sin egen tråd, så varje anrop skall klara av att köras utan att behöva vänta på något annant anrop (om man nu inte har låst någon tabeller eller så).
Det skulle betyda att man så fall har 5.000 - 10.000 trådar att hålla reda på. Bara overheaden på att hålla reda på dessa trådar skulle sluka minst 50 % av CPU kraften, på en normal dator.
Sedan 5000 -10000 samtidiga anslutningar till databasen är extremt mycket, även om man inte gör något med anslutningen så måsta SQL Servern ändå tilldela den resurser för att kunna hantera den. Om man skriver sin kod rätt så skulle typ 50-100 anslutningar till databasen lätt kunna hantera dessa 5.000 - 10.000 klienter, eftersom alla klienter knappast måste läsa till databasen exakt samtidigt.
nickemannen skrev:
NHibernate som jag har gjort en del nu så är den arkitekturen mer connected eftersom man måste ha den uppkopplad om man vill använda lazyload osv.
Nu kan jag inget om NHibernate, men om det är som du säger så verkar det vara en extremt dålig lösning. Det är väl inget som säger att du måste hålla kopplingen till databasen öppen för att du vill hämta data senare, att du kanske måste hålla samma NHibernate objekt öppet kan jag förstå, men att de inte skulle kunna stänga kopplingen till databasen är för mig rent ut sagt skit. Och jag skulle aldrig använda det om det var implementerat så, bara tanken på hur resten av koden så ut skulle göra mig mörkrädd. Men jag tror dock inte på dig riktigt, men som sagt jag har aldrig använt det så jag vet inte.
Jag vet inte exakt hur en Ms Sql Server fungerar men att den skapar en tråd för varje anslutning skulle jag isåfall tycka vore en dum grej.
En socket kan jag förstå och sedan att den skulle skapa en tråd för varje arbete den skall utföra.
Under min utbildning hade vi en som doktorerade i just nätverk osv, och vi frågade honom om det vore en bra lösning att skapa en tråd per anslutning i ett liknande server klient fall, och då sa han att det var en mycket dum lösning, utan man skulle ha alla socket i en lista som man sedan lyssnade på efter data och sedan vid eventuellt arbete så skulle man skapa en ny tråd för den socketen som sedan dog när arbetet var utfört.
En socket kan jag förstå och sedan att den skulle skapa en tråd för varje arbete den skall utföra.
Mycket möjligt, har som sagt ingen anning, bara att det blir en del overhead med att ha en massa anslutningar även om de inte gör något.
nickemannen skrev:
Och som ni beskriver hur connectionpoolingen fungerar med .net så verkar det ju som att den har kvar kopplingen ändå. :S.
Ja och det är ju det som är själva poängen, att du har typ 50-100 aktiva anslutningar som bara ligger och väntar på att få exekvera data, istället för 5000-10000 aktiva anslutningar.
User connections specifies the number of concurrent users that are allowed on Microsoft SQL Server. Since each user connection consumes 40 KB of memory space, a high number of user connections can impact throughput and cause a performance slow-down. Use this metric to gain an overview of high access periods and to warn you of impending availability problems.
Så 10.000 uppkopplingar skulle sno 400 MB av ditt ram minne, och det kan ju verkligen användas bättre än så.
En socket kan jag förstå och sedan att den skulle skapa en tråd för varje arbete den skall utföra.
Mycket möjligt, har som sagt ingen anning, bara att det blir en del overhead med att ha en massa anslutningar även om de inte gör något.
nickemannen skrev:
Och som ni beskriver hur connectionpoolingen fungerar med .net så verkar det ju som att den har kvar kopplingen ändå. :S.
Ja och det är ju det som är själva poängen, att du har typ 50-100 aktiva anslutningar som bara ligger och väntar på att få exekvera data, istället för 5000-10000 aktiva anslutningar.
- M
Okej, men med en arkitektur där varje program/användaren bara har en koppling mot databasen och aldrig öppnar eller använder sig av fler så borde det väl inte vara någon fara då?
400 Mb för 10.000 användare låter inte så farligt.
Men jag håller med dig det är ju ändå 400 MB och det tar prestanda, frågan är bara vad som är enklast att utveckla osv.. Det är ju egentligen där den stora kostnaden ligger.
Jag tycker ämnet är högst intressant, tror jag skall gräva lite i detta på jobbet imorgon.
Okej, men med en arkitektur där varje program/användaren bara har en koppling mot databasen och aldrig öppnar eller använder sig av fler så borde det väl inte vara någon fara då?
Det låter inte som en bra arkitektur, eftersom du vill ju ha möjligheten att kunna parallellisera flera anrop mot databasen kanske. Då kommer ju en applikation vilja göra flera anslutningar samtidigt kanske 2-5 stycken för att få bättre svarstider.
nikemannen skrev:
400 Mb för 10.000 användare låter inte så farligt.
400 MB för att inte göra något låter ganska farligt i mina öron.
nicekmannen skrev:
frågan är bara vad som är enklast att utveckla osv..
Enklast att utveckla är om du överlåter det till connection poolen att hantera uppkoplingarna. Du skall helt enkelt inte bry dig om det överhuvudtaget, det viktiga som du skall göra är att se till så att det händer så lite som möjlig mellan det att du öppnar och koppling och innan du stänger den.
Om connectionpoolen ändå innehåller 2-5 eller fler anslutningar öppna mot sql servern så upptar ju egentligen den dessa 400 MB som inte gör någonting om jag fattat det rätt?
Det är sant att man kanske skulle vilja göra flera förfrågningar samtidigt mot databasen från samma klient, vet inte riktigt hur det påverkar prestandan att ställa flera frågor samtidigt eller att ta dom efter varandra, det borde väl bero på hur måna kärnor servern har och möjligtvis klientdatorn.
Jag förstår ju absolut att detta kan vara en ganska big deal vid ASP.NET lösningar då det bara är en applikation som har en connectionpool, men när det gäller winform så är jag kluven.
Förstår inte hur du menar med ASP.NET och att det är skillnad där, connectionpool ligger per connectionstring, så det är inget specifikt för asp.net utan ado.net, om du inte har byggt din lösning så olika installationer har olika anslutningar. Och oavsett vad så blir det bra mycket bättre prestanda med pooling eller inte, det är ju framtaget för förhindra resursslukande vid skapande av anslutningar. Trots du har en gemensam pool på en asp.net så har du ju även en pool på din enskilda app. Lösningen kanske är att ta ett SOA-approach till dina tjänster för att dela. Men jag är faktiskt inte heler säker på att inte ADO.NET snackar med MSSQL och låter den sköta connectionpoolingen, men jag tror det är ramverket som hanterar det själv :)
Minnet kanske blir det samma om den ligger i poolen, men det tar prestanda från sql-servern att skapa ett "connectionobjekt", det är det som tar kräm. Det tar inte alls lika mycket prestanda att återanvända ett från poolen.
Om connectionpoolen ändå innehåller 2-5 eller fler anslutningar öppna mot sql servern så upptar ju egentligen den dessa 400 MB som inte gör någonting om jag fattat det rätt?
Hmmm... så du tänker alltså att du har 2-5 öppna anslutningar i din connectionpool per klient. Så om du har 10.000 klienter så har du mellan 20.000 och 50.000 öppna anslutningar! Du det har jag aldrig ens tänkt på, men jag hoppas att fallet inte är så, utan att connectionpoolen ligger synkad mot servern på något sätt. Så att du fortfarande bara har 2-5 öppna anslutningar även om du har 10.000 klienter. Men det tål verkligen att tänkas på... skall se om man hittar något.
Nickemannen skrev:
vet inte riktigt hur det påverkar prestandan att ställa flera frågor samtidigt eller att ta dom efter varandra, det borde väl bero på hur måna kärnor servern har och möjligtvis klientdatorn.
Rent krast så kan man säga att prestandan blir sämre på servern men användaren kommer uppfatta det som bättre :)
Tänk så här. Du har 5 SQL frågor som skall exekveras efter varandra, varje fråga tar 1 minut att genomföra. I ett synkront scenario (en tråd) så kommer svaret efter 5 minuter. I ett scenario med flera trådar så kommer svaret tillbaka efter 1 minut. Eftersom du kör de 5 frågorna samtidigt. Nu kanske servern får lite sämre prestanda eftersom du exekverar 5 frågor samtidigt, så slutresultatet blir att det tar 2 minuter. Så även om det tar mer resurser från servern i anspråk så kommer klienten att uppfatta det som om det gått fortare.
Om connectionpoolen ändå innehåller 2-5 eller fler anslutningar öppna mot sql servern så upptar ju egentligen den dessa 400 MB som inte gör någonting om jag fattat det rätt?
Hmmm... så du tänker alltså att du har 2-5 öppna anslutningar i din connectionpool per klient. Så om du har 10.000 klienter så har du mellan 20.000 och 50.000 öppna anslutningar! Du det har jag aldrig ens tänkt på, men jag hoppas att fallet inte är så, utan att connectionpoolen ligger synkad mot servern på något sätt. Så att du fortfarande bara har 2-5 öppna anslutningar även om du har 10.000 klienter. Men det tål verkligen att tänkas på... skall se om man hittar något.
Exakt, när det inte gäller en asp.net koppling så borde poolen bara innehålla en koppling om inte flera program kör mot samma databas. Då skulle det ju kunna hända att den har fler om den får oturen att det utförs saker på kopplingen samitidigt.
279 ms totalt · 4 externa anrop · v20260731065814-full.1dc6f849