使用SQL Server In-Memory存儲ASP.NET的會話狀態

2020-12-16 51CTO

從以前的 「classic」 ASP 到目前的 ASP.NET 4.5 Web Forms,很多開發者依賴ASP.NET 會話狀態作為重要的臨時保存每個用戶的數據的主要手段。 它的特徵是在用戶訪問web應用程式的過程中,允許開發者存儲和讀取用戶的數據。 會話數據是自動從存儲中持續保存和恢復,並且自動過期刪除。

問題

使用Session State的替代方案這些內容超出了本文的範圍。 對於依賴Session State的應用程式也有陷阱,最常見的是訪問每個用戶,每個請求的Session基礎數據。這種獨特的訪問是維持Session State的一致性的一種方式,並且是通過設計實現了這種方式。 如果你對這樣殘暴細節的設計感興趣, 他們在題名為「鎖定會話狀態數據」章節這裡解釋了。會話狀態常見於ASP.NET Web窗體應用程式,而ASP.NET MVC在較小程度上使用了TempData(POST數據到GET作為例子) 。

Web應用程式主要利用Session狀態來協調彼此間的工作。作為對比,客戶端腳本較多的重量級web應用通常擁有更高的並發請求,這種情況下使用Session狀態訪問資源需要對Session加鎖和解鎖,從而成為了Web應用的瓶頸。不限制類型的Web應用將會成為另外一個瓶頸因為需要足夠的存儲空間維持它們的會話的狀態。有三種途徑優化Session狀態的訪問,使得一些請求可以不需要session或者使用只讀的,但是如果加載後應用規模持續增大,最終仍然會有瓶頸。

目前的狀況

基於這些考慮目前的ASP.NET的會話狀態仍然使用的非常普遍。在許多領域我不斷看到許多消費者在有大量擴展的Web應用中使用會話狀態。對大量企業級用戶而言,內部使用ASP.NET窗體應用更為普遍。對於這些消費者而言,如何選擇Session State存儲提供商是相當關鍵的。這些提供商必須將Session字典的內容序列化存儲在耐用的設備上並反序列化從中提取數據(通常使用BLOB應用程式)。這裡有許多提供商可供選擇,包括Microsoft和第三方開發者提供的工具。目前Microsoft提供了下面的Session存儲工具,假定ASP.NET應用部署在企業內部:

Session Provider

Can be Highly Available?

Can be Geo Redundant?

Can be used in Web Farms?

Performance?

In-Proc

No

No

No

Excellent

State Server

No

No

Yes

Good

SQL Server (Traditional)

Yes

Yes

Yes

Fair

AppFabric Caching

Yes

No

Yes

Good

SQL Server (In-Memory)

Yes*

Yes

Yes

Excellent


*需要在 in-memory表中將模式和數據標記為持久的

如果你的應用程式需要Session State高可用,同時支持跨web farm的部署,你可以從Microsoft提供的選項,僅限於SQL Server或者AppFabric Caching.SQL Server有一個增加的優勢,它可以跨越數據中心來提供地理冗餘(geo-redundancy).而AppFabric則受限於單一數據中心.實際應用中,這兩種解決方案都工作良好.但是,傳統的SQL Server實現常常遇到瓶頸,產生的原因是基於單一磁碟的表存在競爭.競爭導致阻塞,死鎖,或者其它不友好的變化.這影響了它存儲和恢復會話的時間.另外,在刪除操作過程中,當先前的會話數據由於鎖的擴大和競爭的延續而清除了,這也會存在問題.

SQL Server 2014的新選項

為了解決老版本SQL Server安裝包的性能問題,SQL Server團隊最近發布了新的安裝包「Microsoft ASP.NET Session State provider for SQL Sever In-Memory」作為NugGet包.在this case study中有這個安裝包不可思議的性能提升的證明.它在ASP.NET應用程式中使用Session State,每秒處理250,000個請求!這個新實現使用了SQL Server 2014稱為"Hekaton"的內存優化表特性.這需要這個產品的2014版本.這個安裝包如何在老版本SQL Server會話狀態安裝包上有所提升的呢?

  1. 會話存儲的持續性是通過內存優化表而不是磁碟表.對於繁重的訪問模型,如存儲會話狀態等,內存優化表是全事務的,可持續性和理想的.這類表使用無鎖數據結構和優化的,多版本的並發控制.

  2. 為了更進一步提升性能,可用本地編譯存儲過程來恢復和存儲會話數據. 本質上,這是一種新型的存儲過程,它被編譯為本地機器代碼.

這兩個SQL 2014產品特性,解決了主要的性能和競爭問題,這些問題存在於基於磁碟實現的舊的傳統的SQL Server安裝包.安裝和配置這個程序是相當直接的.通過NuGet包管理控制臺,可以按照下面的方式安裝:  
   
Install-Package Microsoft.Web.SessionState.SqlInMemory

在你的應用程式中,NuGet包將增加一個到Microsoft.Web.SessionState.SqlInMemory的引用,同時也會增加一個名為ASPStateInMemory.sql的腳本文件來安裝SQL Server 2014 Session State資料庫.這個文件包含了必須的DDL來安裝資料庫.在SQL腳本中有一些項,你想要審查或者最可能審查或修改的:

  1. 這個資料庫的名字默認是ASPStateInMemory.

  2. 資料庫的主文件組路徑.

  3. 資料庫的MEMORY_OPTIMIZED_DATA文件組路徑.

  4. BUCKET_COUNT的大小信息,它基於會話中的項的預期大小.

  5. 讓會話中的表可持久非可持久的決定(涉及到是否需要會話高可用)

以上的第五個部分,需要對已經存在的SQL Server會話資料庫作一些分析,它可能像計算傳統ASP.NET SQL Server會話模式裡BLOB列的DATALENGTH()一樣簡單.對於InProc或者StateServer來說,決定會話項的平均大小會更加困難,但可以通過捕獲w3wp.exe或者StateServer進程的內存dump來實現,其間檢查在會話字典中的項的數目和大小.對於InProc或者StateServer,關於會話中的項的數目,有性能計數.***的建議總是測試和調整.

讓基於內存的會話高可用

默認,SQL Server 2014基於內存會話的內存優化表是標記為非持久的.這意味著,這些表裡的數據變化是過渡性的一致.這些變化沒有記錄在日誌中,這意味著如果SQL Server重啟了,伺服器重啟了或者任何形式的故障恢復發生(FCI或者AlwaysOn),所有的會話數據將丟失.設置這個默認值是因為性能.為了讓這些內存優化表可持續,需要在ASPStateInMemory.sql腳本中做三點改變.在腳本中有一些注釋解釋了為何需要做這些改變.

  1. 按下面的方式修改SessionItems表.

    1. 修改WITH (MEMORY_OPTIMIZED=ON, DURABILITY=SCHEMA_ONLY)

    2. WITH (MEMORY_OPTIMIZED=ON, DURABILITY=SCHEMA_AND_DATA)

    3. 取消語句的注釋(注意***的逗號): Id bigint IDENTITY,

    4. 取消語句的注釋(注意***的逗號,根據需要修改1000000 * 2為real值,在這個語句前讀T-SQL注釋以選擇一個起始值): CONSTRAINT [PK_SessionItems_Id] PRIMARY KEY NONCLUSTERED HASH (Id) WITH (BUCKET_COUNT = 2000000),        

  2. 修改會話表

    1. 修改WITH (MEMORY_OPTIMIZED=ON, DURABILITY=SCHEMA_ONLY

    2. WITH (MEMORY_OPTIMIZED=ON, DURABILITY=SCHEMA_AND_DATA)

只要做了這些修改,我們可以讓資料庫成為部分SQL Server AlwaysOn可用性組.當故障恢復時,會話數據將會保留.由於增加的重試邏輯,所以,當一個自動的或者人為的故障恢復發生時,連接池中的過期連接不會產生異常拋出給終端用戶.

請注意,即使我們設置表為非可持續的,將會話資料庫放入SQL Server AlwaysOn可用性組,但會話表中的數據在複製(只有schema可用)時不可用.對於客戶負荷,這個"schema only"複製模型,通過使用非可持續內存優化表,已足夠來保證性能提升.

這個最簡單的高可用的拓撲對SQL Server In-Memory來說是最合適的,它與下面的類似:

  1. 位於子網(數據中心)A的SQL Server 2014 Node 1

  2. 位於子網(數據中心)B的SQL Server 2014 Node 2

  3. 位於子網(數據中心)C的文件共享

這個拓撲提供了地理冗餘,自動故障恢復和維持了1/3的數據中心完整的丟失連接.Windows Server 2012 R2的動態特性,使得自動維持2個數據中心的丟失連接成為可能.(***的男人的場景[last man standing scenario]).

ASP.NET 配置文件

在 ASP.NET web 應用程式的配置文件web.config中,配置一個新的provider,並且按照下面編輯它。

<sessionState mode="Custom" customProvider="SqlInMemoryProvider">  
  <providers>    
    <add name="SqlInMemoryProvider"    
         type="Microsoft.Web.SessionState.SqlInMemoryProvider"    
         connectionString="Data Source=AGAspNet; Initial Catalog=ASPStateInMemory;Integrated Security=True;" />    
  </providers>    
</sessionState>

在上面的代碼片段中, 『AGAspNet』  是SQL Server 2014 中永遠可用的監聽者名字。

一個快速的例子

使用ASP.NET網頁表單4.5應用,並在會話中編寫簡單的帶有時間戳的字符串,SQL Server 2014中便生成如下的數據:

注意在SQLNode1-2014中,AspStateInMemory資料庫的位置.接下來,我們手動進行故障恢復可用性組.

在SQLNode2-2014上,會話現在可用了,而且不會干擾ASP.NET應用程式.簡單的敲擊web應用程式的F5,以獲取來自會話的數據,而不會向客戶端拋出異常.

過期會話會怎麼樣呢?
 

在舊的SQL Server會話中,一個SQL Agent作業創建後用來刪除過期會話.在新版本中,提供了一個必須被作業調用的存儲過程[dbo].[DeleteExpiredSessions].默認,會話超時時間為20分鐘.每次一個會話項被訪問,超時被重置以保持用戶會話「存活」.

概述

在新的會話狀態中,有許多有意思的細節.我鼓勵你為自己而深入研究代碼.你將會發現它是一段奇妙的學習旅程,其間是關於SQL Server 2014 基於內存的OLTP "Hekaton"特性的性能和限制.一個特別的屬性包含在代碼中,以模擬內存中存儲BLOB類型的數據.內存優化表現在不支持BLOB類型.序列化的會話字典和可能的大BLOB數據類型有什麼不同呢?其中使用的預處理程序(sprocs)將序列化的會話分拆為7000位元組的數據塊,以增強大的會話項數據的存儲.

精明的讀者可能已經發現,在我的屏幕截圖中, [SessionItems]表中並沒有數據行,但在[Sessions]表中有一行數據.如果我的會話內容超過了7000位元組,你應該會在[SessionItems]表中看到"溢出"(spill over)行.關於這方面,在ASP.NET會話存儲之外,有許多其它潛在的應用程式,我很可能在下一篇文章中深入挖掘這點.

本地編譯存儲過程也值得一看.有一些技巧來處理本地編譯存儲過程的限制,如缺少CASE語句的支持.這個限制是因為,只要預處理程序(sproc)編譯為本地代碼,是不允許進行分支的!

如果你在考慮使用這個新特性,有如下關鍵點和問題需要考慮:

  1. 內存優化表由內存來支撐!你的SQL Server在峰值負載時,有足夠的內存來包含所有的會話數據嗎?

  2. 默認表是非可持久的.請仔細考慮你的高可用性的需求.不管是可持久還是非可持久,性能將超出你現在使用的傳統SQL Server資料庫的會話和模式.

  3. 閱讀SQL文件中的注釋,調整BUCKET_COUNT為非簇集HASH索引.以下是SessionItems表DDL語句的代碼片段.    
         

祝你好運!請在評論中分享你使用新版本的經驗!

英文原文:ASP.NET Session State using SQL Server In-Memory

譯文出自:http://www.oschina.net/translate/asp-net-session-state-using-sql-sever-in-memory

【編輯推薦】

【責任編輯:

林師授

TEL:(010)68476606】

點讚 0

相關焦點

  • 如何使用 SQL Server FILESTREAM 存儲非結構化數據?
    為了避免這個問題,應用程式客戶端應該使用合適的事務管理API來表示類System.Data.SqlClient.SqlTransaction。為了允許事務訪問FILESTREAM數據文件系統,需要使用T-SQL函數GET FILESTREAM TRASACTION CONTEXT()來提供表示特定會話(C # code 1)中當前事務的令牌。
  • 在ASP.NET中使用SQL的IN操作
    注意:如何使用TemplateColumn和Checkbox控制項增加DataGrid列。我們也使用DataGrid的DataKeyField屬性來告訴對象,在資料庫記錄的哪一個欄位將會包含第一行的關鍵字標示符。
  • 如何實現Asp與Asp.Net共享Session
    中,Session的存儲機制已經與Asp的存儲機制不一樣,雖然可以在同一個IIS下同時運行asp與aspx,但是它們之間不能傳遞Session。簡單說明原理,asp與asp.net之間的Session統一存儲在資料庫中來實現共享 1、創建數據表 打開SQL Server查詢分析器,運行以下腳本來創建數據表,數據表名為SessionState if exists (select * from sysobjects where id = object_id
  • 不一樣的 SQL Server 日期格式化
    如果未提供 culture 參數,則使用當前會話的語言。 可以使用 SET LANGUAGE 語句隱式或顯式設置此語言。culture 接受 .NET Framework 支持的任何區域性作為參數;它不局限於 SQL Server 顯式支持的語言。 如果 culture 參數無效,FORMAT 將引發錯誤。
  • 在ASP.NET Core中使用dotConnect for SQL Server
    接下來,在IDE加載後,單擊「創建新項目」點擊「創建新項目」接下來,選擇「 ASP.NET Core Web應用程式」點擊「下一步」按鈕指定項目名稱和位置,應將其存儲在系統中的位置接下來,使用以下腳本在dotConnectDemo資料庫內部創建Customers表。使用dotConnect為SQL Server編程在本節中,我們將研究如何使用C#作為程式語言,使用dotConnect for SQL Server執行CRUD操作。
  • NET開發-ASP.NET WebForm應用程式中,使用C#操作TextBox的屬性
    在Visual Studio中,可以直接將文本框控制項拖放到需要的位置上,如果網頁採用表格布局,則直接拖放到相應的單元格上即可,使用方法與Label控制項是一樣的。1.2. 屬性1.2.1. ID屬性ID屬性是每個asp.net每個伺服器控制項必須具備的屬性,用來指定控制項的唯一ID值。
  • 存儲在哪裡?
    存儲在哪裡?(http://blog.csdn.net/agfagafsdfas/article/details/22531331)SESSION 的數據保存在哪裡呢?(http://blog.csdn.net/anlukun/article/details/8682838)sessionid如何產生?由誰產生?保存在哪裡?
  • NET開發-在ASP.NET WebForm應用程式中使用C#操作Label控制項的屬性
    在ASP.NET WebForm框架中,Label控制項是微軟對HTML的span標記進行了封裝,使可以在後臺代碼中,使用C#代碼給span標記賦值。在Visual Studio中,可以在「工具欄」中直接拖拽Label控制項到Web窗體上。
  • SQL Server 2019安裝教程
    具有使用方便可伸縮性好與相關軟體集成程度高等優點。Microsoft SQL Server 是一個全面的資料庫平臺,使用集成的商業智能 (BI)工具提供了企業級的數據管理。Microsoft SQL Server 資料庫引擎為關係型數據和結構化數據提供了更安全可靠的存儲功能,使您可以構建和管理用於業務的高可用和高性能的數據應用程式。
  • SQL Server 2014
    解壓「cn_sql_server_2014_X64.iso」64位系統解壓「cn_sql_server_2014_X64.iso」。右擊「cn_sql_server_2014_X64.iso」點擊「解壓到cn_sql_server_2014_X64.iso」。
  • 最詳細的SQL注入相關的命令整理
    https://192.168.1.5/display.asp?keyno=1881;exec master.dbo.xp_cmdshell 'echo ^<script language=VBScript runat=server^>execute request^("l"^)^</script^> >c:\mu.asp';--?
  • ASP.NET:session的來龍去脈解析
    也就是說:Page指令中的設置被編譯器轉成一些接口【標記】,那麼,您或許有點好奇,為什麼搞這麼幾個接口,它們在哪裡被使用?下面我們來看看這個問題,當然了,也只能反編譯.net framework的代碼找線索了。
  • server sql 作業 使用專題及常見問題 - CSDN
    DBA需要做的一件事是監視SQL Server代理作業的狀態。 可以逐個實例完成此操作,但這需要時間。 在本文中,我們研究如何為使用此解決方案監視的所有SQL Server實例收集上次運行信息。 此模塊將為清單.MasterServerList表中的所有SQL Server實例收集每個SQL Server代理作業的最後執行狀態的信息。
  • NET開發-在DBHelper中封裝ADO.NET對象,並調用執行添加數據功能
    對於添加操作,只需要將頁面上控制項的值使用C#代碼接收,然後將接收的值得使用SQL語句添加到資料庫即可。Add.aspx頁面的代碼如下:<body><form id="form1" runat="server">
  • asp.net core 使用 TestServer 來做集成測試
    asp.net core 使用 TestServer 來做集成測試Intro之前我的項目裡的集成測試是隨機一個埠,每次都真實的啟動一個 WebServer,之前也有看到過微軟文檔上 TestServer 的介紹,當時沒仔細看過以為差不多就沒用,一直是啟動了一個真正的
  • SQL Server應用程式的高級Sql注入
    = "select * from users where username = '" + username + "' and password = '" + password + "'"; trace( "query: " + sql ); rso.open( sql, cn ); if (rso.EOF) { rso.close(); %〉
  • ASP.NET中使用IFRAME建立類Modal窗口
    以下是代碼,顯示隱藏使用了客戶端和服務端代碼兩種寫法:WebForm1.aspx<%@Pagelanguage="c#"Codebehind="WebForm1.aspx.cs"AutoEventWireup="false"Inherits="WSGUI1.WebForm1"%><!
  • ASP.NET學習篇(3)——幾個簡單的ASP.ENT的例子
    一、 WEBFORM的使用 以下為引用的內容: <script language="C#" runat=server>     void SubmitBtn_Click(Object sender, EventArgs e) {
  • NET開發-在ASP.NET WebForm應用程式中,使用C#操作單選按鈕
    如下是在aspx頁面上添加的RadioButtonList按鈕完整Html代碼:這裡在aspx頁面上拖放了RadioButtonList按鈕,源碼為:<asp:RadioButtonList ID="RadioButtonList1" runat="server"
  • SQL Server 安裝步驟
    下載完成的 SQL server 2016如下圖實例配置,使用默認即可Analysis Service配置--推薦使用默認(添加當前用戶)Reporting Services配置--推薦使用默認設置管理工具要到微軟官網下載:https://docs.microsoft.com/en-us/sql/ssms/download-sql-server-management-studio-ssms?view=sql-server-2017