ASP.NET會話(Session)保存模式

【原創】ASP.NET會話(Session)保存模式

作者寒羽楓(cityhunter172)

 

大家好,已有四個多月沒寫東東啦。今日抽空就說一下 Session .Net v1.0/v1.1 中的存儲模式。大家可在 MSDN 2003 中搜索一下 <sessionState> 即可看到關於 Web.config 中的<sessionState> 節點元素的描述,共有 OffInProcStateServerSQLServer 四種模式。OffInProc 分別指“不啓用”、“進程內保存(默認值)”,此兩種模式沒啥講的,所謂 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 代理” 右擊“作業” 點擊“新建作業” 輸入 “名稱”(此例爲 GrantSessionUser 點擊標籤 “步驟” 新建 輸入 “步驟名”(此例爲 Grant01 選擇數據庫“tempdb 編寫 SQL 腳本“exec sp_adduser 'SessionStateUser', 'SessionUser' ,'db_owner' ”→ 確定 點擊標籤 “調度” 新建 輸入 “名稱”(此例爲 Start01 )→ 選擇類型“SQL Server 代理啓動時自動啓動” 確定 最後點擊“確定”新增完畢

 

 

 

 

C)、也可運行以下腳本一次性搞定以上 AB 兩個步驟

/******腳本開始******/

      --新建數據庫帳號 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”,則使用本地計算機ASPNETWindows 2000 系統帳戶)或 Network ServiceWindows 2003 系統帳戶)的身份登錄數據庫。要是數據庫不允許上述用戶登錄,則報錯;同樣,即使上述帳戶能成功登錄,也要分配其 tempdb 的權限,理由是 Session 是保存在 tempdb 中的,若沒有該 DataBase 的存取權限是行不滴。見下圖:

 

 

寒羽楓(cityhunter172

2006-05-14 00:01 完稿 

 

 



Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=727743

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章