大家好,已有四個多月沒寫東東啦。今日抽空就說一下 Session 在 .Net v1.0/v1.1 中的儲存模式。大家可在 MSDN 2003 中搜尋一下 <sessionState> 即可看到關於 Web.config 中的<sessionState> 節點元素的描述,共有 Off、InProc、StateServer、SQLServer 四種模式。Off、InProc 分別指“不啟用”、“進程內儲存(預設值)”,此兩種模式沒啥講的,所謂 InProc 就是把 Session 儲存在 aspnet_wp.exe (Windows 2000 解析 ASP.NET頁面所用的進程) 或 w3wp.exe (Win2003 的進程) 中,一旦進程被中止或被重設,Session 將丟失。
一、 引發 Session 丟失的幾種原因
動過手寫代碼的人都知道,Session 丟失是比較常見的事。以下是本人這幾年所遇到的,能夠引發 Session 丟失的原因,不敢說是百分百,丟失機率還是特別高的。錯…,簡直可以說是“相…當…”高哇 ^_^"
1、 存放 Session 的電腦重啟(廢話,若這樣都不丟,你神仙啊)
2、 InProc 模式:aspnet_wp.exe 或 w3wp.exe 在“工作管理員”中或其它情況下導致其進程被終止運行。
3、 InProc 模式:修改 .cs 檔案後,編譯了兩次(只編譯一次,有時不會丟失)
4、 InProc 模式:修改了 Web.config
5、 InProc 模式,Windows 2003 環境:應用程式集區回收、停止後重啟
6、 InProc 模式:伺服器上 bin 目錄裡的 .DLL 檔案被更新
以上列舉的都是 InProc 模式下,容易引發解析 ASP.NET 應用程式重設的原因。是不是覺得很窩火?之前我也有這種感覺,慢慢就習慣啦,再後來就乾脆不用這種模式了。於是乎,就有了使用下列兩種模式的嘗試,現寫出來與大家一起分享。
二、 使用 StateServer 儲存 Session
StateServer 模式的實質是,把Session 存放在一個單獨的進程裡,此進程獨立於 aspnet_wp.exe 或 w3wp.exe 。啟用此服務後,在“工作管理員”中可以看到一個名為 aspnet_state.exe 的進程,下面開始說明一下設定的具體步驟:
1、 修改註冊表(關鍵步驟,如)
運行 regedit → 開啟註冊表 → 找到HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Services/aspnet_state/Parameters 節點 → 將 AllowRemoteConnection 的索引值設定成“1”(1 為允許,0 代表禁止)→ 設定 Port (連接埠號碼)
注意事項:
a)、若ASP.NET State Service 正在運行,修改註冊表內容後,則需要重新啟動該服務
b)、注意連接埠號碼的索引值是以十六進位儲存的,可以使用十進位進行修改,42424 是預設的連接埠
c)、AllowRemoteConnection 的索引值設定成“1”後,意味著允許遠程電腦的串連,也就是說只要知道你的服務連接埠,就可享用你的ASP.NET State Service,即把 Session 存放在你的電腦進程內,因此請大家慎用;索引值為“0”時,僅有stateConnectionString 為“tcpip=localhost: 42424”與“tcpip=127.0.0.1:42424”的情況,方可使用ASP.NET State Service.
2、 開啟 ASP.NET State Service(如)
右鍵點擊“我的電腦”→ 管理 → 服務與應用程式 → 服務 → 雙擊“ASP.NET State Service” → 啟動(可設為“自動”)
說明:只要安裝了 .Net Framework v1.0/v1.1 ,都擁有此服務。
3、 更改 Web.config
開啟 Web.config → 找到 <sessionState> 節點內容
<sessionState
mode="InProc"
stateConnectionString="tcpip=127.0.0.1:42424"
sqlConnectionString="data source=127.0.0.1;Trusted_Connection=yes"
cookieless="false"
timeout="20" />
→ 將其改為以下內容
<sessionState mode="StateServer" stateConnectionString="tcpip=192.168.0.2:42424" timeout="20" />
注意事項:
a)、設成StateServer 後,必須要有對應的stateConnectionString
b)、注意 IP 位址(可以是遠端電腦 IP、電腦名稱、網域名稱)與連接埠號碼,連接埠號碼需與ASP.NET State Service 的服務連接埠一致
三、 將 Session 放入 SQLServer 儲存
SQLServer 模式就是,把Session 存放在 SQL Server 資料庫裡(注意不是 Oracle ,動動腳趾都能猜到原因啦),下面開始說明一下設定的具體步驟:
1、 啟動相關的資料庫服務()
運行SQL Server 服務管理器 → 啟動 SQL Server (最好設為開機自動運行) → 啟動 SQL Server Agent 服務(最好設為開機自動運行)
注意事項:
a)、注意啟動順序,也可通過下列方式設定: 右鍵點擊“我的電腦”→ 管理 → 服務與應用程式 → 服務 → 找到“MSSQLSERVER”與“SQLSERVERAGENT” → 啟動並設定啟動類型為“自動”
b)、SQL Server Agent在此處的作用是清除資料庫中已到期的 Session
2、 建立存放 Session 的 DataBase
運行“SQL 查詢分析器”→ 使用“sa”或是擁有“master”的 db_owner 許可權的使用者登入資料庫 → 開啟查詢檔案 C:/WINNT/Microsoft.NET/Framework/v1.1.4322/InstallSqlState.sql (存放在 Windows 系統目錄的 .Net 安裝目錄下可找到) → 直接運行該 sql 指令碼 → 重新整理資料庫即可看到名為 ASPState 的 DataBase
3、 建立串連資料庫 ASPState 的使用者,並為此使用者授權(此步驟可跳過)
進行此步的原因是:一是不想在 Web.config 中出現 sa 的密碼;二是 tempdb 在資料庫啟動後僅保留 sa 一個帳號的使用許可權,其餘帳號的許可權統統被清除,但儲存 Session又需要用到此 DataBase;
A)、運行 SQL Server 的企業管理器 → 展開資料庫的安全性 → 右擊“登入” → 建立“登入” → 輸入“名稱” → 選擇 “SQL Server 身分識別驗證” → 輸入“密碼” → 指定“資料庫” → 點擊“資料庫訪問” → 勾選 “ASPState” → 選中“db_owner”角色 → 點擊“確定” → 再一次輸入“密碼” → 點擊“確定” 後即可建立 ASPState 的使用者(此處建立名為“SessionStateUser”,密碼為“123456”的測試使用者)
B)、運行 SQL Server 的企業管理器 → 展開“管理” → 展開“SQL Server Agent” → 右擊“作業” → 點擊“新增作業” → 輸入 “名稱”(此例為 GrantSessionUser ) → 點擊標籤 “步驟” → 建立 → 輸入 “步驟名”(此例為 Grant01) → 選擇資料庫“tempdb” → 編寫 SQL 指令碼“exec sp_adduser 'SessionStateUser', 'SessionUser' ,'db_owner' ”→ 確定 → 點擊標籤 “調度” → 建立 → 輸入 “名稱”(此例為 Start01 )→ 選擇類型“SQL Server Agent啟動時自動啟動” → 確定 → 最後點擊“確定”新增完畢
C)、也可運行以下指令碼一次性搞定以上 A、B 兩個步驟
/******指令碼開始******/
--建立資料庫帳號 SessionStateUser ,預設登入 ASPState
EXEC sp_addlogin 'SessionStateUser', '123456', 'ASPState'
use ASPState --切換 DataBase
--將 SessionStateUser 授予 db_owner 的許可權
exec sp_adduser 'SessionStateUser', 'SessionUser' ,'db_owner'
use master --切換 DataBase
BEGIN TRANSACTION
/******聲明變數******/
DECLARE @JobID BINARY(16)
DECLARE @ReturnCode INT
SELECT @ReturnCode = 0
-- 若沒有,則添加作業的分類
IF (SELECT COUNT(*) FROM msdb.dbo.syscategories WHERE name = N'[Uncategorized (Local)]') < 1
EXECUTE msdb.dbo.sp_add_category @name = N'[Uncategorized (Local)]'
-- 新增作業
EXECUTE @ReturnCode = msdb.dbo.sp_add_job --調用預存程序 sp_add_job
@job_id = @JobID OUTPUT, --將返回的 JobID,賦值給變數
@job_name = N'GrantSessionUser', --作業名稱
@owner_login_name = NULL, --預設為目前使用者所有
@description = null,
@category_name = N'[Uncategorized (Local)]', --作業分類歸屬
@enabled = 1, --是否啟用
@notify_level_email = 0,
@notify_level_page = 0,
@notify_level_netsend = 0,
@notify_level_eventlog = 0,
@delete_level= 0
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback --出錯則復原
-- 建立步驟
EXECUTE @ReturnCode = msdb.dbo.sp_add_jobstep --調用預存程序 sp_add_jobstep
@job_id = @JobID, --傳入剛剛建立的 JobID
@step_id = 1,
@step_name = N'Grant01', --步驟名稱
@command = N'exec sp_adduser ''SessionStateUser'', ''SessionUser'' ,''db_owner''',
--需要執行的 SQL 指令碼(注意用兩個連續的單引號表示 SQL 中的單引號)
@database_name = N'tempdb', --執行上述 SQL 所用的 DataBase
@server = N'',
@database_user_name = N'',
@subsystem = N'TSQL', --執行類型為“Transact-SQL 指令碼”
@cmdexec_success_code = 0,
@flags = 0,
@retry_attempts = 0,
@retry_interval = 1,
@output_file_name = N'',
@on_success_step_id = 0,
@on_success_action = 1,
@on_fail_step_id = 0,
@on_fail_action = 2
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
-- 建立調度
EXECUTE @ReturnCode = msdb.dbo.sp_add_jobschedule
@job_id = @JobID,
@name = N'Start01', --調度名稱
@enabled = 1,
@freq_type = 64 --“64”表示 當 SQLServerAgent 服務啟動時運行
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
-- 將建立的作業添加到本機資料庫
EXECUTE @ReturnCode = msdb.dbo.sp_add_jobserver @job_id = @JobID, @server_name = N'(local)'
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
COMMIT TRANSACTION
GOTO EndSave
QuitWithRollback:
IF (@@TRANCOUNT > 0) ROLLBACK TRANSACTION
EndSave:
/******指令碼結束******/
4、 設定 Web.config 內容
開啟 Web.config → 找到 <sessionState> 節點內容 → 修改為以下內容即可:
<sessionState mode="SQLServer" sqlConnectionString ="data source=192.168.0.2; user id= SessionStateUser; password=123456" timeout="20" />
注意事項:
a)、sqlConnectionString 中不能出現 initial catalog 選項
b)、SQL Server Agent在此處的作用是清除資料庫中已到期的 Session
c)、你若跳過了第三步,則 user id 需要用 sa 進行登入
d)、若sqlConnectionString 為 “data source=127.0.0.1;Trusted_Connection=yes”,則使用本機電腦ASPNET(Windows 2000 系統帳戶)或 Network Service(Windows 2003 系統帳戶)的身份登入資料庫。要是資料庫不允許上述使用者登入,則報錯;同樣,即使上述帳戶能成功登入,也要分配其 tempdb 的許可權,理由是 Session 是儲存在 tempdb 中的,若沒有該 DataBase 的存取許可權是行不滴。見:
作者:寒羽楓(cityhunter172)
轉自:http://blog.csdn.net/cityhunter172/article/details/727743