当前位置: 首页 > 科技观察

使用SQLServerIn-Memory存储ASP.NET会话状态

时间:2023-03-13 16:27:05 科技观察

从以前的“经典”ASP到现在的ASP.NET4.5WebForms,很多开发者都依赖ASP.NET会话状态作为每个用户的重要临时存储数据的主要手段。它的特点是允许开发者在用户访问网络应用的过程中存储和读取用户数据。会话数据自动持久化并从存储中恢复,并自动过期和删除。问题使用会话状态的替代方案这些超出了本文的范围。依赖会话状态的应用程序也存在缺陷,最常见的是访问基于每个用户、每个请求的会话数据。这种独特的访问是一种保持会话状态一致性的方法,它是通过这种方式设计的。如果您对这种极其详细的设计感兴趣,可以在此处标题为“锁定会话状态数据”的部分中对其进行解释。会话状态在ASP.NETWeb窗体应用程序中很常见,而ASP.NETMVC在较小程度上使用TempData(以POST数据到GET为例)。Web应用程序主要使用会话状态来协调它们的工作。相比之下,具有更多客户端脚本的重量级Web应用程序通常具有更高的并发请求。在这种情况下,使用Session状态访问资源需要对Session进行加锁和解锁,成为web应用的瓶颈。不受限制类型的Web应用程序将成为另一个瓶颈,因为它们需要足够的存储空间来维护它们的会话状态。可以通过三种方式来优化Session状态的访问,让一些请求不需要session或者只读,但是如果应用规模在loading之后继续增大,最终还是会出现瓶颈。当前情况基于这些考虑,当前的ASP.NET会话状态仍然很常见。在许多领域,我一直看到会话状态被许多消费者在具有很大规模的Web应用程序中使用。对于大量的企业用户来说,内部使用ASP.NET表单应用程序更为普遍。对于这些消费者来说,如何选择一个SessionState存储提供商是相当关键的。这些提供者必须序列化会话字典的内容以存储在持久设备上,并反序列化以从中提取数据(通常使用BLOB应用程序)。这里有许多提供商可供选择,包括来自Microsoft和第三方开发人员的工具。目前微软提供了以下会话存储工具,假设企业内部部署了ASP.NET应用程序:SessionProviderCanbeHighlyAvailable?可以异地冗余吗?可以在网络场中使用吗?表现?In-Proc否否优秀的状态服务器否否是良好的SQLServer(传统)是是是公平的AppFabric缓存web对于场部署,您可以从Microsoft提供的选项仅限于SQLServer或AppFabric缓存。SQLServer具有能够跨越数据中心以提供地域冗余的额外优势。AppFabric仅限于单一数据中心。在实践中,这两种解决方案都运行良好。然而,传统的SQLServer实现往往会因为基于单个磁盘的表争用而遇到瓶颈。争用会导致阻塞、死锁或其他不友好的更改。这会影响存储和恢复会话所需的时间。此外,在删除操作期间,如果先前的会话数据由于锁扩展和竞争的继续而被清除,这可能会出现问题。SQLServer2014为了解决旧版SQLServer安装包的性能问题,SQLServer团队近日发布了新的安装包“MicrosoftASP.NETSessionStateproviderforSQLSeverIn-Memory”作为一个NugGet包。在这个案例研究中,有证据表明这个已安装的包具有令人难以置信的性能提升。它在每秒处理250,000个请求的ASP.NET应用程序中使用会话状态!这个新实现使用SQLServer2014有一个内存优化表功能叫做“Hekaton”,这个需要2014版本的产品,这个包对老版本的SQLServer会话状态包有什么改进?会话存储是通过内存优化表而不是磁盘来持久化的基于内存的表。内存优化表是完全事务性的、持久的,非常适合重访问模型,例如存储会话状态。此类表使用无锁数据结构和优化的多版本并发控制。为了进一步提高性能,原生编译存储过程可以用来恢复和存储session数据,本质上这是一种编译成native机器码的新型存储过程,这两个SQl2014产品特性解决了旧传统基于磁盘的SQLServer安装包存在的主要性能和竞争问题。安装和配置该程序非常简单。通过NuGet包管理控制台,可以安装如下:Install-PackageMicrosoft.Web.SessionState.SqlInMemory。在您的应用程序中,NuGet包将添加对Microsoft.Web.SessionState.SqlInMemory的引用,并添加一个名为ASPStateInMemory.sql的脚本文件以安装SQLServer2014会话状态数据库。此文件包含安装数据库所需的DDL。SQL脚本中有一些项目您想要查看或最有可能查看或修改:默认情况下,数据库的名称是ASPStateInMemory。数据库的主文件组路径。数据库的MEMORY_OPTIMIZED_DATA文件组路径。BUCKET_COUNT的大小信息,基于session中item的预期大小。决定session中的表是持久化还是非持久化(涉及到session是否需要高可用)上面第五部分,需要现有的SQLServersession个数对数据库进行一些分析,可能就像在传统ASP.NETSQLServer会话模式下计算BLOB列的DATALENGTH()一样简单。对于InProc或StateServer,确定会话条目的平均大小会更加困难,但可以通过w3wp.exe或StateServer进程的内存转储捕获,在此期间它会检查会话字典中条目的数量和大小。对于InProc或StateServer,有关于会话中条目数的性能计数。最好的建议始终是测试和调整。使基于内存的会话高可用默认情况下,基于内存会话的SQLServer2014内存优化表被标记为非持久性。这意味着这些表中的数据更改是暂时一致的。这些更改不会记录在日志中,这意味着如果重新启动SQLServer、重新启动服务器或发生任何形式的故障转移(FCI或AlwaysOn),所有会话数据都将丢失。这个默认值是为了性能而设置的。要使这些内存优化表可持续,您需要在ASPStateInMemory.sql脚本中进行三处更改。脚本中有一些注释解释了为什么需要进行这些更改。按如下方式修改SessionItems表。将WITH(MEMORY_OPTIMIZED=ON,DURABILITY=SCHEMA_ONLY)改为WITH(MEMORY_OPTIMIZED=ON,DURABILITY=SCHEMA_AND_DATA)取消语句的注释(注意***的逗号):idbigintIDENTITY,取消语句的注释(注意***的逗号,根据需要修改1000000*2为真实值,在这条语句之前阅读T-SQL注释选择一个起始值):CONSTRAINT[PK_SessionItems_Id]PRIMARYKEYNONCLUSTEREDHASH(Id)WITH(BUCKET_COUNT=2000000),修改会话表修改WITH(MEMORY_OPTIMIZED=ON,DURABILITY=SCHEMA_ONLYisWITH(MEMORY_OPTIMIZED=ON,DURABILITY=SCHEMA_AND_DATA)只要进行这些修改,我们就可以让数据库成为SQLServerAlwaysOnAvailabilityGroup的一部分。当故障恢复时,会话数据将被保留。由于增加了重试逻辑,所以,当发生自动或人为的故障恢复时,连接池中的过期连接不会产生异常抛给最终用户。请注意,即使我们将表设置为非持久性,将会话数据库放入SQLServerAlwaysOn可用性组,但会话表中的数据在复制期间不可用(仅模式)。对于客户工作负载,这种“仅模式”复制模型,通过使用不可持续的内存优化表,足以保证性能提升。最简单的高可用拓扑最适合SQLServerIn-Memory,类似如下:SQLServer2014Node1locatedinsubnet(datacenter)ASQLServer2014Node1locatedinsubnet(datacenter)B服务器2014节点2位于子网(数据中心)C文件共享此拓扑提供地理冗余、自动故障转移并保持1/3的数据中心完全失去连接。WindowsServer2012R2的动态特性使得自动维护2个数据中心丢失的连接成为可能。(***男人的场景[最后一个男人站立的场景])。ASP.NET配置文件在ASP.NETweb应用的配置文件web.config中,配置一个新的provider,编辑如下在上面的代码片段中,“AGAspNet”是SQLServer2014中始终可用的侦听器名称。一个使用ASP.NETWebForms4.5应用程序并在会话中写入简单的时间戳字符串的快速示例在SQLServer2014中生成以下数据:请注意AspStateInMemory数据库在SQLNode1-2014中的位置。接下来,我们手动故障转移可用性组。在SQLNode2-2014上,会话现在可用而不会干扰ASP.NET应用程序。只需在Web应用程序上按F5即可从会话中获取数据,同时不会向客户端抛出异常。过期的会话会怎样?在旧的SQLServer会话中,创建了一个SQL代理作业来删除过期的会话。在新版本中,提供了一个必须由作业过程[dbo].[DeleteExpiredSessions]调用的存储。默认情况下,会话超时为20分钟。每次访问会话条目时,都会重置超时以保持用户会话“有效”。概述在新的会话状态中,有很多有趣的细节。我鼓励您自己深入研究代码。您会发现这是一次关于SQLServer2014基于内存的OLTP“Hekaton”功能的性能和限制的惊人学习之旅。代码中包含一个特定属性,用于模拟在内存中存储BLOB类型的数据。内存优化表目前不支持BLOB类型。序列化会话字典和可能的大型BLOB数据类型之间有什么区别?其中使用的预处理器(sprocs)将序列化的session拆分成7000字节的数据块,以增强大session项数据的存储。细心的读者可能已经发现,在我的截图中,[SessionItems]表中没有数据行,但是[Sessions]表中有一行数据。如果我的会话内容超过7000字节,您应该会在[SessionItems]表中看到“溢出”行。关于这一点,除了ASP.NET会话存储之外,还有很多其他潜在的应用,我可能会在下一篇文章中深入探讨。本机编译的存储过程也值得一看。有一些技巧可以解决本地编译存储过程的局限性,例如缺少CASE语句支持。这个限制是因为,只要预处理器(sproc)被编译成本地代码,就不允许分支!如果您正在考虑使用此新功能,则需要考虑以下关键点和问题:内存优化表由内存支持!当您的SQLServer处于峰值负载时,您有足够的内存来包含所有会话数据?默认表是非持久的。请仔细考虑您的高可用性要求。无论是持久的还是非持久的,其性能都将超过您目前使用的传统SQLServer数据库的会话和架构。读取SQL文件中的Comment,调整BUCKET_COUNT为非聚集HASH索引。下面是SessionItems表的DDL语句的代码片段。祝你好运!请在评论中分享您对新版本的体验!英文原文:ASP.NETSessionStateUsingSQLServerIn-Memory翻译自:http://www.oschina.net/translate/asp-net-session-state-using-sql-sever-in-memory