कई लोगों ने अपने परिवेश में ASPState को लागू किया है। कुछ लोग इन-मेमोरी विकल्प (इनप्रोक) का उपयोग करते हैं, लेकिन आमतौर पर मुझे डेटाबेस विकल्प का उपयोग किया जा रहा है। यहां कुछ संभावित अक्षमताएं हैं जिन्हें आप कम मात्रा वाली साइटों पर नोटिस नहीं कर सकते हैं, लेकिन यह आपके वेब वॉल्यूम रैंप के रूप में प्रदर्शन को प्रभावित करना शुरू कर देगा।
रिकवरी मॉडल
सुनिश्चित करें कि ASPState सरल पुनर्प्राप्ति के लिए सेट है - यह नाटकीय रूप से लॉग पर प्रभाव को कम करेगा जो उच्च मात्रा (क्षणिक और बड़े पैमाने पर डिस्पोजेबल) के कारण हो सकता है जो यहां जाने की संभावना है:
ALTER DATABASE ASPState SET RECOVERY SIMPLE;
आम तौर पर इस डेटाबेस को पूर्ण पुनर्प्राप्ति में होने की आवश्यकता नहीं होती है, खासकर यदि आप आपदा पुनर्प्राप्ति मोड में हैं और अपने डेटाबेस को पुनर्स्थापित कर रहे हैं, तो आखिरी चीज जिसके बारे में आपको चिंता करनी चाहिए, वह आपके वेब ऐप में उपयोगकर्ताओं के लिए सत्र बनाए रखने की कोशिश कर रही है - जिनके होने की संभावना है जब तक आपने पुनर्स्थापित किया है तब तक लंबे समय तक चले जाओ। मुझे नहीं लगता कि मैं कभी ऐसी स्थिति में आया हूं जहां एएसपीस्टेट जैसे क्षणिक डेटाबेस के लिए पॉइंट-इन-टाइम रिकवरी एक आवश्यकता थी।
I/O को छोटा/अलग करें
प्रारंभ में ASPState की स्थापना करते समय, आप -sstype c
. का उपयोग कर सकते हैं और -d
सत्र स्थिति को एक कस्टम डेटाबेस में संग्रहीत करने के लिए तर्क जो पहले से ही एक अलग ड्राइव पर है (जैसे आप tempdb के साथ करेंगे)। या, यदि आपका tempdb डेटाबेस पहले से ही अनुकूलित है, तो आप -sstype t
. का उपयोग कर सकते हैं बहस। इन्हें सत्र-राज्य मोड और MSDN पर ASP.NET SQL सर्वर पंजीकरण उपकरण दस्तावेज़ों में विस्तार से समझाया गया है।
यदि आप पहले से ही ASPState स्थापित कर चुके हैं, और आपने निर्धारित किया है कि आप इसे अपने स्वयं के (या कम से कम एक अलग) वॉल्यूम में ले जाने से लाभान्वित होंगे, तो आप एक संक्षिप्त रखरखाव अवधि के लिए शेड्यूल या प्रतीक्षा कर सकते हैं और इन चरणों का पालन कर सकते हैं:पी>
डाटाबेस एएसपीस्टेट को तत्काल रोलबैक के साथ SINGLE_USER सेट करें; डेटाबेस एएसपीस्टेट ऑफ़लाइन सेट करें; वैकल्पिक डेटाबेस ASPState संशोधित फ़ाइल (NAME =ASPState, FILENAME ='{नया पथ}\ASPState.mdf'); वैकल्पिक डेटाबेस ASPState संशोधित फ़ाइल (NAME =ASPState_log, FILENAME ='{नया पथ}\ASPState_log.ldf');
इस बिंदु पर आपको फ़ाइलों को मैन्युअल रूप से <new path>
. पर ले जाना होगा , और फिर आप डेटाबेस को वापस ऑनलाइन ला सकते हैं:
डाटाबेस एएसपीस्टेट ऑनलाइन सेट करें; ALTER DATABASE ASPState MULTI_USER सेट करें;
एप्लिकेशन अलग करें
एक ही सत्र राज्य डेटाबेस में एक से अधिक एप्लिकेशन को इंगित करना संभव है। मैं इसके खिलाफ अनुशंसा करता हूं। संसाधन उपयोग को बेहतर ढंग से अलग करने और अपनी सभी वेब संपत्तियों के लिए अत्यधिक लचीलापन प्रदान करने के लिए, आप शायद अलग-अलग डेटाबेस पर अनुप्रयोगों को इंगित करना चाहें, शायद अलग-अलग उदाहरणों पर भी।
यदि आपके पास पहले से ही एक ही डेटाबेस का उपयोग करने वाले कई एप्लिकेशन हैं, तो यह ठीक है, लेकिन आप प्रत्येक एप्लिकेशन के होने वाले प्रभाव का ट्रैक रखना चाहेंगे। माइक्रोसॉफ्ट के रेक्स टैंग ने प्रत्येक सत्र द्वारा खपत की गई जगह को देखने के लिए एक उपयोगी क्वेरी प्रकाशित की; यहां एक संशोधन दिया गया है जो प्रति आवेदन सत्रों की संख्या और कुल/औसत सत्र आकार को संक्षेप में प्रस्तुत करेगा:
सेलेक्ट ए.एपनाम, सेशनकाउंट =COUNT(s.SessionId), TotalSessionSize =SUM(DATALENGTH(s.SessionItemLong)), AvgSessionSize =AVG (DATALENGTH(s.SessionItemLong)) dbo से। ASPStateTempApplications as a on SubSTRING(s.SessionId, 25, 8) =SUBSTRING(sys.fn_varbintohexstr(CONVERT(VARBINARY(8)), a.AppId)), 3, 8) Group by a.AppNameORDER by TotalSessionSize DESC;
यदि आप पाते हैं कि आपके यहां एकतरफा वितरण है, तो आप कहीं और ASPState डेटाबेस सेट कर सकते हैं, और इसके बजाय उस डेटाबेस पर एक या अधिक एप्लिकेशन इंगित कर सकते हैं।
अधिक दोस्ताना तरीके से हटाएं
dbo.DeleteExpiredSessions
. के लिए कोड एक DELETE
. के स्थान पर कर्सर का उपयोग करता है पहले के कार्यान्वयन में। (यह, मुझे लगता है, काफी हद तक ग्रेग लो द्वारा इस पोस्ट पर आधारित था।)
मूल रूप से कोड था:
CREATE DeleteExpiredSessionas रूप में DECLARE @now DATETIME SET @now =GETUTCDATE() DELETE ASPState..ASPStateTempSessions जहां समाप्त हो रहा है <@now RETURN 0GO
(और यह अभी भी हो सकता है, इस पर निर्भर करता है कि आपने स्रोत कहां से डाउनलोड किया है, या आपने कितनी देर पहले एएसपीस्टेट स्थापित किया है। डेटाबेस बनाने के लिए वहां कई पुरानी स्क्रिप्ट हैं, हालांकि आपको वास्तव में aspnet_regsql.exe का उपयोग करना चाहिए।)
वर्तमान में (.NET 4.5 के अनुसार), कोड इस तरह दिखता है (किसी को भी पता है कि Microsoft सेमी-कोलन का उपयोग कब शुरू करेगा?)।
परिवर्तन प्रक्रिया [dbo]। [DeleteExpiredSessions] सेट DEADLOCK_PRIORITY LOW DECLARE @now datetime SET @now =GETUTCDATE() क्रिएट टेबल #tblExpiredSessions (SessionID nvarchar(88) NOTSION PRIMARY INSERT INSERT ) [ASPState] से सत्र आईडी चुनें। समाप्त सत्र कर्सर से अगला @SessionID जबकि @@ FETCH_STATUS =0 [ASPState] .dbo.ASPStateTempSes से हटाएं जहां सत्र आईडी =@ सत्र आईडी और समाप्त हो जाता है <@ अब समाप्त सत्र कर्सर से अगला प्राप्त करें @ सत्र आईडी समाप्त हो गया समाप्त सत्र समाप्त समाप्त हो गया सत्र कर्सर समाप्त हो गया सत्र कर्सर अंत ड्रॉप तालिका #tblExpiredSession वापसमेरा विचार है कि यहां एक खुशहाल माध्यम हो - एक झटके में सभी पंक्तियों को हटाने की कोशिश न करें, लेकिन एक-एक करके एक-एक-एक अजीब-सी न खेलें। इसके बजाय,
n
हटाएं अलग-अलग लेन-देन में एक समय में पंक्तियाँ - अवरोधन की लंबाई को कम करना और लॉग पर प्रभाव को कम करना:वैकल्पिक प्रक्रिया dbo.DeleteExpiredSessions @top INT =1000ASBEGIN SET NOCOUNT ON; DECLARE @now DATETIME, @c INT; चुनें @now =GETUTCDATE (), @c =1; लेनदेन शुरू करें; जबकि @c <> 0 BEGIN; x AS के साथ (dbo.ASPStateTempSessions से चुनें टॉप (@top) सत्र आईडी जहां समाप्त हो जाता है <@ अब सत्र आईडी द्वारा आदेश) एक्स हटाएं; सेट @c =@@ ROWCOUNT; IF @@ TRANCOUNT =1 कमिट ट्रांजैक्शन शुरू करें; लेनदेन शुरू करें; END END IF @@ TRANCOUNT =1 कमिट ट्रांजैक्शन शुरू करें; ENDENDGOआप
TOP
के साथ प्रयोग करना चाहेंगे आपका सर्वर कितना व्यस्त है और अवधि और लॉकिंग पर इसका क्या प्रभाव पड़ता है, इस पर निर्भर करता है। आप स्नैपशॉट अलगाव को लागू करने पर भी विचार कर सकते हैं - यह tempdb पर कुछ प्रभाव डालेगा लेकिन ऐप से देखे गए अवरोध को कम या समाप्त कर सकता है।साथ ही, डिफ़ॉल्ट रूप से, कार्य
ASPState_Job_DeleteExpiredSessions
हर मिनट चलता है। इसे थोड़ा पीछे डायल करने पर विचार करें - शायद हर 5 मिनट में शेड्यूल को कम करें (और फिर, इसमें से बहुत कुछ कम हो जाएगा कि आपके एप्लिकेशन कितने व्यस्त हैं और परिवर्तन के प्रभाव का परीक्षण कर रहे हैं)। और दूसरी तरफ, सुनिश्चित करें कि यह सक्षम है - अन्यथा आपकी सत्र तालिका अनियंत्रित होकर बढ़ेगी।सत्रों को कम बार स्पर्श करें
हर बार एक पृष्ठ लोड होने पर (और, यदि वेब ऐप सही ढंग से नहीं बनाया गया है, संभवतः प्रति पृष्ठ लोड कई बार), संग्रहीत कार्यविधि
dbo.TempResetTimeout
कहा जाता है, यह सुनिश्चित करते हुए कि उस विशेष सत्र के लिए समयबाह्य तब तक बढ़ाया जाता है जब तक वे गतिविधि उत्पन्न करना जारी रखते हैं। एक व्यस्त वेब साइट पर, यह तालिकाdbo.ASPStateTempSessions
के विरुद्ध बहुत अधिक मात्रा में अद्यतन गतिविधि का कारण बन सकता है . यहाँdbo.TempResetTimeout
. के लिए वर्तमान कोड है :परिवर्तन प्रक्रिया [डीबीओ]।अब, कल्पना कीजिए कि आपके पास 500 या 5,000 उपयोगकर्ताओं के साथ एक वेब साइट है, और वे सभी एक पृष्ठ से दूसरे पृष्ठ पर पागलपन से क्लिक कर रहे हैं। यह संभवत:किसी भी ASPState कार्यान्वयन में सबसे अधिक बार बुलाए जाने वाले संचालनों में से एक है, और जब तालिका
SessionId
पर कुंजीबद्ध होती है - इसलिए किसी भी व्यक्तिगत बयान का प्रभाव न्यूनतम होना चाहिए - कुल मिलाकर यह लॉग सहित, काफी हद तक बेकार हो सकता है। यदि आपका सत्र टाइमआउट 30 मिनट का है और आप वेब ऐप की प्रकृति के कारण हर 10 सेकंड में एक सत्र के लिए टाइमआउट अपडेट करते हैं, तो 10 सेकंड बाद इसे फिर से करने का क्या मतलब है? जब तक उस सत्र को 30 मिनट से पहले किसी बिंदु पर असीमित रूप से अपडेट किया जाता है, तब तक उपयोगकर्ता या एप्लिकेशन में कोई शुद्ध अंतर नहीं होता है। इसलिए मैंने सोचा कि आप सत्रों को उनके टाइमआउट मानों को अपडेट करने के लिए "स्पर्श" करने के लिए एक अधिक स्केलेबल तरीका लागू कर सकते हैं।एक विचार मेरे पास एक सेवा दलाल कतार को लागू करना था ताकि आवेदन को वास्तविक लिखने के लिए इंतजार न करना पड़े - यह
dbo.TempResetTimeout
को कॉल करता है। संग्रहीत प्रक्रिया, और फिर सक्रियण प्रक्रिया अतुल्यकालिक रूप से लेती है। लेकिन यह अभी भी बहुत अधिक अपडेट (और लॉग गतिविधि) की ओर ले जाता है, जो वास्तव में आवश्यक है।एक बेहतर विचार, IMHO, एक कतार तालिका को लागू करना है जिसे आप केवल सम्मिलित करते हैं, और एक शेड्यूल पर (जैसे कि प्रक्रिया टाइमआउट से कम समय में एक पूर्ण चक्र पूरा करती है), यह केवल किसी भी सत्र के लिए टाइमआउट को अपडेट करेगा। देखता है एक बार , इससे कोई फर्क नहीं पड़ता कि उन्होंने उस अवधि के भीतर अपने टाइमआउट को अपडेट करने के लिए कितनी बार *कोशिश की*। तो एक साधारण तालिका इस तरह दिख सकती है:
तालिका dbo.SessionStack(SesionId tSessionId, -- nvarchar(88) - निश्चित रूप से उन्हें उपनाम प्रकार EventTime DATETIME का उपयोग करना था, संसाधित बिट नहीं पूर्ण डिफ़ॉल्ट 0); dbo.SessionStack(EventTime);GOपर क्लस्टर्ड इंडेक्स और क्रिएट करेंऔर फिर हम सत्र गतिविधि को सीधे सत्र तालिका को छूने के बजाय इस स्टैक पर सत्र गतिविधि को आगे बढ़ाने के लिए स्टॉक प्रक्रिया को बदल देंगे:
प्रक्रिया बदलें dbo.TempResetTimeout @id tSessionIdASBEGIN SET NOCOUNT ON; dbo.SessionStack(SessionId, EventTime) में डालें @id, GETUTCDATE ();ENDGOचुनेंसंकुल अनुक्रमणिका
smalldatetime
. पर है पृष्ठ विभाजन को रोकने के लिए कॉलम (हॉट पेज की संभावित कीमत पर), क्योंकि सत्र स्पर्श के लिए घटना का समय हमेशा एकरस रूप से बढ़ता रहेगा।फिर हमें
dbo.SessionStack
में नई पंक्तियों को समय-समय पर सारांशित करने के लिए एक पृष्ठभूमि प्रक्रिया की आवश्यकता होगी और अपडेट करेंdbo.ASPStateTempSessions
तदनुसार।CREATE PROCEDURE dbo.SessionStack_ProcessASBEGIN SET NOCOUNT ON; -- जब तक आप tSessionId को मॉडल में या मैन्युअल रूप से tempdb में नहीं जोड़ना चाहते -- प्रत्येक पुनरारंभ के बाद, हमें यहां आधार प्रकार का उपयोग करना होगा:CREATE TABLE #s(SessionId NVARCHAR(88), EventTime SMALLDATETIME); -- स्टैक अब आपका हॉटस्पॉट है, इसलिए जल्दी से अंदर और बाहर जाएं:UPDATE dbo.SessionStack SET प्रोसेस्ड =1 OUTPUT इन्सर्ट किया गया।SessionId, इंसर्ट किया गया। EventTime INTO #s WHERE प्रोसेस्ड IN (0,1) - यदि कोई अंतिम बार विफल हुआ हो समय और घटना समयआप इसके आसपास और अधिक लेन-देन नियंत्रण और त्रुटि प्रबंधन जोड़ना चाह सकते हैं - मैं सिर्फ एक ऑफ-द-कफ विचार प्रस्तुत कर रहा हूं, और आप इसके आसपास जितना चाहें उतना पागल हो सकते हैं। :-)
आप सोच सकते हैं कि आप
dbo.SessionStack(SessionId, EventTime DESC)
पर एक गैर-संकुल अनुक्रमणिका जोड़ना चाहेंगे। पृष्ठभूमि प्रक्रिया को सुविधाजनक बनाने के लिए, लेकिन मुझे लगता है कि उपयोगकर्ता द्वारा प्रतीक्षा की जाने वाली प्रक्रिया (प्रत्येक पृष्ठ लोड) पर सबसे छोटे प्रदर्शन लाभ पर भी ध्यान केंद्रित करना बेहतर है, क्योंकि वे (पृष्ठभूमि प्रक्रिया) की प्रतीक्षा नहीं करते हैं। इसलिए मैं हर एक इंसर्ट के दौरान अतिरिक्त इंडेक्स रखरखाव के भुगतान के बजाय पृष्ठभूमि प्रक्रिया के दौरान संभावित स्कैन की लागत का भुगतान करना चाहूंगा। #temp टेबल पर क्लस्टर इंडेक्स के साथ, यहां बहुत कुछ "यह निर्भर करता है", इसलिए आप इन विकल्पों के साथ खेलना चाहते हैं यह देखने के लिए कि आपकी सहनशीलता सबसे अच्छी तरह से कहां काम करती है।जब तक कि दो ऑपरेशनों की आवृत्ति में बहुत अधिक अंतर न हो, मैं इसे
ASPState_Job_DeleteExpiredSessions
के भाग के रूप में शेड्यूल करूंगा। जॉब (और अगर ऐसा है तो उस जॉब का नाम बदलने पर विचार करें) ताकि ये दोनों प्रक्रियाएं एक-दूसरे को रौंदें नहीं।यहां एक अंतिम विचार है, यदि आप पाते हैं कि आपको और भी अधिक विस्तार करने की आवश्यकता है, तो एक से अधिक
SessionStack
बनाना है टेबल, जहां प्रत्येक सत्र के सबसेट के लिए जिम्मेदार होता है (जैसे,SessionId
के पहले अक्षर पर हैशेड) ) फिर आप प्रत्येक तालिका को बारी-बारी से संसाधित कर सकते हैं, और उन लेन-देन को इतना छोटा रख सकते हैं। वास्तव में आप डिलीट जॉब के लिए भी कुछ ऐसा ही कर सकते हैं। यदि सही तरीके से किया जाता है, तो आप इन्हें अलग-अलग कार्यों में लगाने और उन्हें एक साथ चलाने में सक्षम होना चाहिए, क्योंकि - सिद्धांत रूप में - डीएमएल को पृष्ठों के पूरी तरह से अलग सेट को प्रभावित करना चाहिए।निष्कर्ष
ये मेरे अब तक के विचार हैं। मुझे ASPState के साथ आपके अनुभवों के बारे में सुनना अच्छा लगेगा:आपने किस तरह का पैमाना हासिल किया है? आपने किस तरह की अड़चनें देखी हैं? आपने उन्हें कम करने के लिए क्या किया है?