asp.net狀態服務和session丟失

來源:互聯網
上載者:User

ASP.NET2.0系統時,在程式中做刪除或建立檔案操作時,出現session丟失問題。
採用了如下方法:
1、asp.net Session的實現:
asp.net的Session是基於HttpModule技術做的,HttpModule可以在請求被處理之前,對請求進行狀態控制,由於Session本身就是用來做狀態維護的,因此用HttpModule做Session是再合適不過了。
ASP.NET中Session的狀態保持方式 
ASP.NET提供了Session對象,從而允許程式員識別、儲存和處理同一個瀏覽器對象對伺服器上某個特定網路應用程式的若干次請求的上下文資訊。Session對應瀏覽器與伺服器的同一次對話,在瀏覽器第一請求網路應用程式的某個頁面時,伺服器會觸發Session_onStart事件;在對話逾時或者被關閉的時候會觸發Session_onEnd 事件。程式員可以在代碼中響應這兩個事件來處理與同一次對話相關的任務,如開闢和釋放該次對話要使用的資源等。
   在ASP.NET的程式中要使用Session對象時,必須確保頁面的@page指令中EnableSessionState屬性是True或者Readonly,並且在web.config檔案中正確的設定了SessionState屬性。
  ASP.NET中Session的狀態保持是由web.config檔案中的<system.web>標記下的<sessionstate>標記的mode屬性來決定的。該屬性有四種可能的值:Off、Inproc、StateServer和SQlServer.
 設為Off會禁用Session.
  Inproc是預設的設定,這種模式和以前的ASP的工作階段狀態的方法是類似的,會話的狀態會被儲存在ASP.NET進程中,它的優點是顯而易見的:效能。進程內的資料訪問自然會比誇進程的訪問快。然而,這種方法Session的狀態依賴於ASP.NET進程,當IIS進程崩潰或者正常重起啟時,儲存在進程中的狀態將丟失。
 為了克服Inproc模式的缺點,ASP.NET提供了兩種進程外保持工作階段狀態的方法。
  ASP.NET首先提供了提供了一個Windows服務:ASPState,這個服務啟動後,ASP.NET應用程式可以將mode屬性設定為“SateServer”,來使用這個Windows服務提供的狀態管理方法。
 除了在web.config檔案中設定mode屬性為StateServer外,還必須設定運行StateServer伺服器的IP地址和連接埠號碼.如果在IIS所在的機器運行StateServer則IP地址就是127.0.0.1,連接埠號碼通常是42424.配置如下:
 mode=”StateServer”
 stateConnectionString="tcpip=127.0.0.1:42424"
    使用這種模式,工作階段狀態的儲存將不依賴IIS進程的失敗或者重啟,會話的狀態將儲存在StateServer進程的記憶體空間中。
   另一種工作階段狀態模式是SQLServer模式。這種模式是將會話的狀態儲存在SQL Server資料庫中的。使用這種模式前,必須至少有一台SQL Server伺服器,並在伺服器中建立需要的表和預存程序。.NET SDK提供了兩個指令碼來簡化這個工作:InstallSqlState.sql和UnInstallSqlState.sql。這兩國檔案存放在下面路徑中:
  <%SYSTEMDRIVER%>\Winnt\Microsoft.NET\Framework\<%version%>\
要配置SQL Server 服務器,可以在命令列中運行SQL Server提供的命令列工具osql.exe
  osql -s [server name] -u [user] -p [password] <InstallSqlState.sql
例如:
  osql -s (local) -u as -p “”-i  InstallSqlState.sql
做好必要的資料庫準備工作後,將web.config檔案中的sessionstate元素的mode屬性改為”sqlserver”,並指定SQL連接字串。具體如下:
  mode="SQLServer"
    sqlConnectionString="data source=127.0.0.1;userid=sa;password=;Trusted_Connection=yes"
使用SQLServer模式處了可以使Session的狀態不依賴於IIS伺服器之外,還可以利用SQL Server的叢集,使狀態儲存不依賴於單個的SQL Server,這樣就可以為應用程式提供極大的可靠性。

 

 
2、丟失原因:
轉(1):Asp.net 預設配置下,Session莫名丟失的原因及解決辦法
      正常操作情況下Session會無故丟失。因為程式是在不停的被操作,排除Session逾時的可能。另外,Session逾時時間被設定成60分鐘,不會這麼快就逾時的。
原因和解決辦法寫出來。
原因:
由於Asp.net程式是預設配置,所以Web.Config檔案中關於Session的設定如下:
<sessionState
mode='InProc'
stateConnectionString='tcpip=127.0.0.1:42424'
sqlConnectionString='data source=127.0.0.1;Trusted_Connection=yes'
cookieless='true'
timeout='60'/>

我們會發現sessionState標籤中有個屬性mode,它可以有3種取值:InProc、StateServer?SQLServer(大小寫敏感)。預設情況下是InProc,也就是將Session儲存在進程內(IIS5是aspnet_wp.exe,而IIS6是W3wp.exe),這個進程不穩定,在某些事件發生時,進程會重起,所以造成了儲存在該進程內的Session丟失。
[asp的Session是具有進程依賴性的。ASP Session狀態存於IIS的進程中,也就是inetinfo.exe這個程式。所以當inetinfo.exe進程崩潰時,這些資訊也就丟失。]

哪些情況下該進程會重起呢?微軟的一篇文章告訴了我們:
1、設定檔中processModel標籤的memoryLimit屬性
2、Global.asax或者Web.config檔案被更改
3、Bin檔案夾中的Web程式(DLL)被修改
4、殺毒軟體掃描了一些.config檔案。
更多的資訊請參考PRB: Session variables are lost intermittently in ASP.NET applications
解決辦法:
      前面說到的sessionState標籤中mode屬性可以有三個取值,除了InProc之外,還可以為StateServer、SQLServer。這兩種存Session的方法都是進程外的,所以當aspnet_wp.exe重起的時候,不會影響到Session。

      現在請將mode設定為StateServer。StateServer是原生一個服務,可以在系統服務裡看到服務名為ASP.NET State Service的服務,預設情況是不啟動的。當我們設定mode為StateServer之後,請手工將該服務啟動。這樣,我們就能利用原生StateService來儲存Session了,除非電腦重啟或者StateService崩掉,否則Session是不會丟的(因Session逾時被丟棄是正常的)。
      除此之外,我們還可以將Session通過其他電腦的StateService來儲存[如使用狀態伺服器]。具體的修改是這樣的。同樣還在sessionState標籤中,有個stateConnectionString='tcpip=127.0.0.1:42424'屬性,其中有個ip地址,預設為本機(127.0.0.1),你可以將其改成你所知的運行了StateService服務的電腦IP,這樣就可以實現位於不同電腦上的Asp.net程式互連Session了。

      如果你有更高的要求,需要在服務期重啟時Session也不丟失,可以考慮將mode設定成SQLServer,同樣需要修改sqlConnectionString屬性。關於使用SQLServer儲存Session的操作,請訪問這裡。
      在使用StateServer或者SQLServer儲存Session時,所有需要儲存到Session的對象除了基礎資料型別 (Elementary Data Type)(預設的資料類型,如int、string等)外,都必須序列化。只需將[Serializable]標籤放到要序列化的類前就可以了。
如:
[Serializable]
public class MyClass
{
    ......
}
具體的序列化相關的知識請參這裡。
至此,問題解決。

參考文章:
ASP.NET Session State FAQ
ASP.NET Session State
[ASP.NET] Session 詳解
PRB: Session Data Is Lost When You Use ASP.NET InProc Session State Mode
PRB: Session Data Is Lost When You Use ASP.NET InProc Session State Mode
ASP.NET HTTP 運行時
.NET 中的對象序列化 
備忘
(1)使用 StateServer 模式
確保運行 ASP.NET 狀態服務的伺服器是要儲存工作階段狀態資訊的遠程伺服器。該服務與 ASP.NET 一起安裝,其預設位置為
<磁碟機>:\systemroot\Microsoft.NET\Framework\version\aspnet_state.exe。
在應用程式的 Web.config 檔案中,
設定 mode=StateServer 並設定 stateConnectionString 屬性。
例如,stateConnectionString="tcpip=sarath:42424"。
(2)使用 SQLServer 模式
在運行 SQL Server 的電腦(它將儲存工作階段狀態)上運行 InstallSqlState.sql
(預設的安裝位置為 <磁碟機>:\systemroot\Microsoft.NET\Framework\version)。
這將建立一個名為 ASPState 的資料庫,該資料庫具有新的預存程序並且在 TempDB 資料庫中具有 ASPStateTempApplications 表和 ASPStateTempSessions 表。
在應用程式的 Web.config 檔案中,設定 mode=SQLServer 並設定 sqlConnectionString 屬性。例如,sqlConnectionString="data source=localhost;Integrated Security=SSPI;Initial Catalog=northwind"。
(3)樣本
以下樣本指定若干工作階段狀態配置設定。

<configuration>
<system.web>
<sessionState mode="InProc"
cookieless="true"
timeout="20"/>
</sessionState>
</system.web>
</configuration>
要求
包含於:<system.web>
Web 平台:IIS 5.0、IIS 5.1、IIS 6.0
設定檔:Machine.config、Web.config
配置節處理常式:System.Web.SessionState.SessionStateSectionHandler
請參見

ASP.NET 配置 | ASP.NET 設定架構 | SessionStateModule
[出現原因:]在Windows2003的伺服器中的IIS6加入了應用程式集區來回收一些無用的進程的功能,當由於網站程式的錯誤或訪問量太多的導致的應用程式集區會自動回收該進程,防止網站進入“死機”狀態,而這時候的應用程式集區的回收就會導致session變數被清除,就出現了session變數不見的現象。
為瞭解決這種在Windows2003下才出現的問題,我們在服務端起動ASP.NET State Service服務,並且在系統的machine.config做了一些改動。現在預設的情況下工作階段狀態mode是StateServer。如果您的網站根目錄下也配有一個web.config設定檔,請把mode="InProc"改成mode="StateServer",如下代碼,就可以防止session變數的丟失:
<sessionState
mode="StateServer"
stateConnectionString="tcpip=127.0.0.1:42424"
sqlConnectionString="data source=127.0.0.1;Integrated Security=SSPI"
cookieless="false"
timeout="30"
/>
+ 註:只適用於支援asp.net的使用者。

 
轉(2):原因及一些解決之道
將Session儲存在State Server裡:
1.啟動服務“ASP.NET State Service”,
2.然後,修改web.config:
<sessionState
mode="StateServer"
stateConnectionString="tcpip=127.0.0.1:42424"
sqlConnectionString="data source=127.0.0.1;Trusted_Connection=yes"
cookieless="false"
timeout="140000"
/>
注意://mode="StateServer"這種模式下即使修改頁面也不會丟失session!
當然:mode="InProc"如果你的模式為這種,修改頁面的時候會丟失session!!!!!!

在WebConfig裡將Session的Mode設成SQLServer或者StateServer都不會丟Session的,
前者需要寫入資料庫,後者需要系統開StateServer服務。
 
原因1:
bin目錄中的檔案被改寫,asp.net有一種機制,為了保證dll重新編譯之後,系統正常運行,它會重新啟動一次網站進程,這時就會導致Session丟失,所以如果有access資料庫位於bin目錄,或者有其他檔案被系統改寫,就會導致Session丟失。[目錄的刪除操作一定丟失session。asp.net的內部機制對待目錄有點像個守財奴,它死守著目錄,你建立它不會管(往裡加),一但建立他就會監視該目錄,若你要刪除或重新命名它的(動它的目錄),它就發生重起了。。]
原因2:
檔案夾選項中,如果沒有開啟“在單獨的進程中開啟檔案夾視窗”,一旦建立一個視窗,系統可能認為是新的Session會話,而無法訪問原來的Session,所以需要開啟該選項,否則會導致Session丟失
原因3:
似乎大部分的Session丟失是用戶端引起的,所以要從用戶端下手,看看cookie有沒有開啟
原因4:
Session的時間設定是不是有問題,會不會因為逾時造成丟失。
[預設時間是20分鐘,可以在Web.Config中設定Session的timeOut,如改為60分鐘等]
原因5:
IE中的cookie數量限制(每個域20個cookie)可能導致session丟失
原因6:
使用web garden模式,且使用了InProc mode作為儲存session的方式
解決丟失的經驗
1. 判斷是不是原因1造成的,可以在每次重新整理頁面的時候,跟蹤bin中某個檔案的修改時間。
2. 做Session讀寫日誌,每次讀寫Session都要記錄下來,並且要記錄SessionID、Session值、所在頁面、當前函數、函數中的第幾次Session操作,這樣找丟失的原因會方便很多
3. 如果允許的話,建議使用state server或sql server儲存session,這樣不容易丟失
4. 在global.asa中加入代碼記錄Session的建立時間和結束時間,逾時造成的Session丟失是可以在SessionEnd中記錄下來的。
5. 如果有些代碼中使用用戶端指令碼,如javascript維護Session狀態,就要嘗試調試指令碼,是不是因為指令碼錯誤引起Session丟失。

 
轉(3):Session丟失原因與解決方案小結
可能的原因1:
win2003 server下的IIS6預設設定下對每個運行在預設應用池中的工作者進程都會經過20多個小時後自動回收該進程,造成儲存在該進程中的session丟失。

因為Session,Application等資料預設儲存在運行該Web應用程式的工作者進程中,如果回收工作者進程,則會造成丟失。

解決辦法:
修改配置,設定為不定時自動回收該工作者進程,比如設定為當超出佔用現有實體記憶體60%後自動回收該進程。通過使用預設應用程式集區,可以確保多個應用程式間互相隔離,保證由於一個應用程式的崩潰不會影響另外的Web應用程式。還可以使一個獨立的應用程式運行在一個指定的使用者帳號特權之下。如果使用StateServer方式或者Sql Server資料庫方式來儲存Session,則不受該設定的影響。

可能的原因2:
系統要運行在Server Load Balancer的 Web 場環境中,而系統設定檔web.config中的Session狀態卻設定為InProc(即在本機存放區工作階段狀態),導至在使用者訪問量大時,Session常經逾時的情況。引起這個現象的原因主要是因為使用者通過Server Load BalancerIP來訪問WEB應用系統,某段時候在某台伺服器儲存了Session的工作階段狀態,但在其它的WEB前端伺服器中卻沒有儲存Session的工作階段狀態,而隨著並發量的增大,Server Load Balancer會當作路由隨時訪問閒置伺服器,結果閒置伺服器並沒有之前儲存的Session工作階段狀態。

解決辦法:
1.當您在Server Load Balancer的 Web 場環境中運行 ASP.NET Web 應用程式時,一定要使用 SqlServer 或 StateServer 工作階段狀態模式,在項目中我們基於效能考慮並沒有選擇SqlServer模式來儲存Session狀態,而是選擇一台SessionStateServer 伺服器來使用者的Session工作階段狀態。我們要在系統設定檔web.config中設定如下:
<sessionState
mode="StateServer" cookieless="false" timeout="240"
stateConnectionString="tcpip=192.168.0.1:42424" stateNetworkTimeout="14400" />
還要添加一項
<machineKey
validationKey="78AE3850338BFADCE59D8DDF58C9E4518E7510149C46142D7AAD7F1AD49D95D4" decryptionKey="5FC88DFC24EA123C" validation="SHA1"/> 

2. 我們同時還要在SessionStateServer 伺服器中啟動ASP.NET State Service服務,具體設定:控制台>>管理工具>>服務>>ASP.NET State Service,把它設為自動啟動即可。

3. 每台前端WEB服務的Microsoft“Internet 資訊服務”(IIS)設定
             要在 Web 場中的不同 Web 服務器間維護工作階段狀態,Microsoft“Internet 資訊服務”(IIS) 設定資料庫中 Web 網站的應用程式路徑(例如,\LM\W3SVC\2)與 Web 場中所有 Web 服務器必須相同。大小寫也必須相同,因為應用程式路徑是區分大小寫。在一台 Web 服務器上,承載 ASP.NET 應用程式的 Web 網站的執行個體 ID 可能是 2(其中應用程式路徑是 \LM\W3SVC\2)。在另一台 Web 服務器上,Web 網站的執行個體 ID 可能是 3(其中應用程式路徑是 \LM\W3SVC\3)。因此,Web 場中的 Web 服務器之間的應用程式路徑是不同的。我們必須使Web 場Web 網站的執行個體 ID 相同即可。你可以在IIS中把某一個WEB配置資訊儲存為一個檔案,其他Web 服務器的IIS配置可以來自這一個檔案。您如果想知道具體的設定請訪問Microsoft Support網站:

 
轉(4):丟失問題集錦
SessionState 的Timeout),其主要原因有三種。
一:有些殺病毒軟體會去掃描您的Web.Config檔案,那時Session肯定掉,這是微軟的說法。
二:程式內部裡有讓Session掉失的代碼,及伺服器記憶體不足產生的。
三:程式有架構頁面和跨域情況。
第一種解決辦法是:使殺病毒軟體屏蔽掃描Web.Config檔案(程式運行時自己也不要去編輯它)
第二種是檢查代碼有無Session.Abandon()之類的。
第三種是在Window服務中將ASP.NET State Service 啟動。
http://community.csdn.net/Expert/topic/3100/3100218.xml?temp=.4426386
還有可能就是你在測試期間改動了,網站的檔案。

下面是協助中的內容:
(ms-help://MS.VSCC.2003/MS.MSDNQTR.2003FEB.2052/cpguide/html/cpconsessionstate.htm)
ASP.NET 提供一個簡單、便於使用的工作階段狀態模型,您可以使用該模型跨多個 Web 請求儲存任意資料和對象。
它使用基於字典的、記憶體中的對象引用(這些對象引用存在於 IIS 進程中)緩衝來完成該操作。
使用進程內工作階段狀態模式時請考慮下面的限制:
使用進程內工作階段狀態模式時,如果 aspnet_wp.exe 或應用程式定義域重新啟動,則工作階段狀態資料將丟失。這些重新啟動通常會在下面的情況中發生:
(1)在應用程式的 Web.config 檔案的 <processModel> 元素中,設定一個導致新進程在條件被滿足時啟動的屬性,例如 memoryLimit。
(2)修改 Global.asax 或 Web.config 檔案。
(3)更改到 Web 應用程式的 \Bin 目錄。
(4)用殺毒軟體掃描並修改 Global.asax 檔案、Web.config 檔案或 Web 應用程式的 \Bin 目錄下的檔案。
(5)如果在應用程式的 Web.config 檔案的 <processModel> 元素中啟用了網路園模式,請不要使用進程內工作階段狀態模式。否則將發生隨機資料丟失。
 
我也碰到過。本機器上的Session或者Cookie丟失。
<sessionState
mode="StateServer"
stateConnectionString="tcpip=127.0.0.1:42424"
sqlConnectionString="data source=127.0.0.1;Trusted_Connection=yes"
cookieless="false"
timeout="40"
/>
mode=""的三個屬性。本地/其他機器/sqlserver。
很多網路架構,各個伺服器之間都是通過一台專門儲存狀態的伺服器(專門的狀態伺服器)來儲存比如說session,cookie..
 
我以前遇到這種問題,我用了以下幾個方法來解決。現在也沒有這種情況發生了。
1、release,不要debug發布。
2、<sessionState cookieless="true" 把cookieless設為true。因為用戶端禁用cookie時,session也無效。
3、在IIS中把Session到期時間延長。
4、讓殺毒軟體不掃描bin檔案夾下的檔案和Web.Config檔案。
以上我是不明不白的做的。不過Session正常使用了!呵呵~~我幸運!
 
沒啥好講的,不要用Session好了,直接用Forms認證把,
我前兩天的系統就是用這個搞定的,覺得挺好的。
剛碰到一個類似的問題:在使用frameset的時候,session變數丟失。
在微軟的網站上找到瞭解決的方法
http://support.microsoft.com/kb/323752/EN-US/
不知道是否有用?

IIS--->>應用程式串連池--->>屬性---->>[回收][效能][健全狀態]裡的各項參數盡量都往大的改^_^),我不知道改拉那個才對的,反正我改完後所有的session都好拉.客戶的網站和動網論壇的後台也跟著好拉。

 
轉(5): 模態視窗中開啟新視窗的session丟失
         一直被這個問題鬱悶。在視窗A中使用showModalDialog()開啟了一個新的模態視窗B。然後在B視窗中進行一些業務操作,最後還需要根據業務操作列印一些表單,結果此時在B中調用open()方法就會出現session丟失的現象,提示使用者重新登陸。
         兩天來一直沒頭蒼蠅一樣不停的實驗各種方法。如果在這個視窗中採用開啟非模態對話方塊的開啟方法showModelessDialog()就沒有任何問題,但是直接使用open()方法就是不能達到想要的效果。在網上不停的google,到各大bbs尋找解答,提供的都是最簡單的應用。好不容易找到一篇文章,其中提到session對象的有效範圍,卻也沒有具體提到我遇到的問題:
IE中:
有效窗品包括
         1.Session對象只在建立Session對象的視窗中有效。
         2.在建立Session對象的視窗中新開連結的視窗無效的視窗包括
         1.直接啟動IE瀏覽器的視窗
         2.不是在建立Session對象的視窗中新開連結的視窗。(即作者在建立Session對象的A視窗彈出的B視窗上調用了open()方法。)
考慮只在建立session對象的視窗中有效,於是就在子視窗中重新使用session.setAttribute()方法,以為如此就可以成功,結果還是不行,鬱悶。
         早上起來突然來了靈感,既然子視窗中造成了session丟失,在父視窗中是無論如何還存在著session的變數的,我可以不必在子視窗中重新設定session變數,而可以直接調用父視窗的javascript函數open()方法可能會到目的吧。不管如何先試試,結果果然如此。   很多時候問題就是這樣的,想要偷懶,於是不自己鑽研,到處尋求解答,最後還是得靠自己來搞定。

本文來自: PQ秀秀網(http://www.pqshow.com) 詳細出處參考:http://www.pqshow.com/program/aspnet/200909/10327.html

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.