65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 PostgreSQL 的会话提供程序示例

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.50/5 (3投票s)

2007 年 4 月 18 日

CPOL

10分钟阅读

viewsIcon

48225

downloadIcon

499

几个用于 TextFile、ODBC 和 PostgreSQL 的自定义会话状态提供程序。

引言

在 ASP.NET 2.0 中,Microsoft 开放了会话状态机制,这样我们就可以使用他们的提供程序概念并创建我们自己的提供程序来存储 ASP.NET 会话状态数据。

背景

自 ASP 时代以来,Microsoft 为我们提供了一种很好的机制,用于在页面调用之间将数据存储在一个名为 Session 的对象中。长期以来,Microsoft 一直控制着会话如何存储其数据。在 ASP.NET 1.1 中,他们提供了三种存储会话数据的选项:进程内、状态服务器和 SQL Server。在 ASP.NET 2.0 中,相同的选项可用,但也可以通过他们的提供程序模型进行自定义。Microsoft 为我们提供了几个会话状态提供程序示例,但我必须看看它们的效果如何。

Issue

如果我们创建了一个自定义提供程序来存储会话状态数据,它是否足以在高性能系统中使用?它需要管理锁定问题。它需要支持 Web 群集。它还需要支持其他什么?Microsoft 文档为我们提供了一份不错的自定义会话状态提供程序需要管理的问​​题列表。

提供程序

快速浏览后,我找到了两个几乎可以立即使用的提供程序:Visual Studio 2005 文档中的 ODBC 提供程序,以及 Microsoft 的“ASP.NET 2.0 提供程序模型”白皮书。我决定试用一下,看看它们是否有效。令人惊讶的是,它们几乎有效。一旦我让它们工作起来,我就想更进一步,尝试一个出色的开源免费 RDBMS:PostgreSQL。由于 PostgreSQL 支持存储过程,所以我创建了一个不使用存储过程的提供程序,以及另一个使用存储过程的提供程序。

对 PostgreSQL 的观察

我曾使用过 Sybase、Informix、SQL Server、Oracle 和一点点 DB2,我想看看 PostgreSQL 在有 MySQL 的情况下能发展得有多好。在使用了一段时间后,它发展得非常好。不久前,我可以很容易地说它领先于 MySQL,而今天我仍然可以这样说。可惜更多的人没有使用它。也许,如果他们阅读了 MySQL 的许可证(我相信最近有所更改)以及这两种产品的功能,他们可能会更多地使用 PostgreSQL。

那么,PostgreSQL 酷在哪里?对于使用 Oracle 的人来说,你会发现 PostgreSQL 原生存储过程语言 PL/pgSQL 很容易从 PL/SQL 切换。你甚至可以用 Tcl、Perl 和 Python 编写存储过程。好的,他们也有 Java 方面的东西。抱歉,C# 部分仍在开发中。它比许多主流 RDBMS 有更多索引类型可供选择。它具有表空间和模式的相似概念。对用户和角色有不错的安全策略。它支持多维数据集、自定义类型、GIS、全文搜索,我将在我揭示它的全部优点之前停下来。我有没有提到它确实处理万亿字节数据库?我有没有提到它是免费的?

那么,PostgreSQL 不酷的地方在哪里?嗯,就是文档。幸运的是,活跃的社区为各种问题提供帮助。你甚至可以每周收到他们正在修复的项目的电子邮件。(“他们正在修复的项目的电子邮件”。这不是一件很酷的事情吗?)我确信文档会随着时间的推移而改进,问题是它能否跟上现在和未来提供的所有内容。UI 管理工具正在改进,但还需要更多的工作。我感觉自己回到了 Oracle 7 时代使用管理工具的时候。我找不到一个“开箱即用”的存储过程调试器。通过观察,在 Windows XP SP2 上,我注意到在执行负载测试时有几个同名进程启动,所以很难说线程的使用是否已经优化。最后,免费版本的 .NET 数据提供程序确实有效,但需要更多的润色才能支持 Microsoft 的企业库,而且文档也需要一些润色。我实际上认为 PostgreSQL 的输出流需要一些润色才能与 .NET 配合得很好,但大多数 RDBMS 都需要在这方面进行改进。对于大多数应用程序来说,这些缺点不是主要障碍,而且你无法超越其成本。

一些小小的补充

在示例提供程序中,有删除旧会话的示例代码。要问的问题是,“你如何做到这一点?”对于 SQL Server,Microsoft 使用代理调用查询来清理旧会话。我认为这很好,但我想知道使用应用程序结束事件。在默认配置中,当 20 分钟没有活动时,ASP.NET 会循环站点。

您可以将以下内容添加到 Web.configsystem.web 部分以更改服务器循环的设置

<!-- Add to system.web to control at application level -->
<hostingEnvironment
    idleTimeout="20"
    shutdownTimeout="30"
/>

当站点正常关闭时,应用程序会触发其结束事件。为了确保这里的所有提供程序都有一个共同的方法来删除旧会话,我在提供程序中添加了一个带有该方法的接口。该接口很简单

public interface IThreeOaksSessionProvider
{
    void DeleteExpiredSessions();
}

一旦我们有了一个通用方法,就可以很容易地在 global.asax.cs 的应用程序结束事件中添加调用以清除过期的会话。在这里,我检查 Web.config 以查看提供程序是什么,以调用适当的提供程序。

protected void Application_End(object sender, EventArgs e)
{
    Debug.WriteLine("Application_End", "global.asax.cs");
       
    //We expect the application to know the provider they are using.
    //So don't do anything fancy to figure out which one's being used.
    Configuration cfg = 
         WebConfigurationManager.OpenWebConfiguration(
         System.Web.Hosting.HostingEnvironment.ApplicationVirtualPath);
    SessionStateSection configSessionStateSection = 
       (SessionStateSection)cfg.GetSection("system.web/sessionState");
    if (configSessionStateSection != null)
    {
        IThreeOaksSessionProvider sessionProvider = null;
        switch (configSessionStateSection.CustomProvider)
        {
            case "PostgreSQLSessionProvider":
                sessionProvider = new PostgreSQLSessionStateStoreSP();
                break;
            case "OdbcSessionProvider":
                sessionProvider = new OdbcSessionStateStore();
                break;
            case "TextFileSessionStateProvider":
                sessionProvider = new TextFileSessionStateStore();
                break;
        }
        if (sessionProvider != null)
        {
            sessionProvider.DeleteExpiredSessions();
        }
    }

由于您应该预先知道正在使用的提供程序,因此应用程序结束过程变得容易得多。以下显示了 PostgreSQLSessionStateStoreSP 的示例

protected void Application_End(object sender, EventArgs e)
{
    Debug.WriteLine("Application_End", "global.asax.cs");
       
    IThreeOaksSessionProvider sessionProvider = new PostgreSQLSessionStateStoreSP();
    sessionProvider.DeleteExpiredSessions();
}

对于那些认为可以从 Session 或 Request 或 Application 中检索 Session State Provider 的人,您可能会遇到困难。当应用程序结束时,为什么会存在任何会话状态提供程序呢?会话尚未导致应用程序结束事件触发。使用大量反射,您实际上可能会检索到一个,但这并不容易。由于在此示例中我们知道我们的提供程序,因此我将其保持简单(KISS)。

观察

那么哪一个效果最好呢?这有点难以抉择。恐怕我没有进行最佳测试的环境。基本上,我正在使用一台运行 Windows XP Professional SP2 的弱鸡笔记本电脑,而我真正需要的是一个 Web 群集。我不敢在我的笔记本电脑上同时运行两三个 Windows Server 虚拟机。

进程内提供程序:

作为一个进程内提供程序,这个提供程序应该在我的弱鸡笔记本电脑上运行得最快。对于我设置的测试,它以 5 个连接每秒运行大约 340 到 360 个请求。我希望我们的自定义提供程序能够与 SQL Server 进程外提供程序匹配,后者似乎以进程内提供程序约 1/4 的请求速度运行。有关一些测试结果,请参阅 提供更好的(ODP 兼容)ASP.NET Session 对象

文本文件会话提供程序:

该提供程序源自 Microsoft 示例。它在我的笔记本电脑上运行良好。在 5 个并发会话下,它大部分时间每秒运行 100 到 120 个请求。由于缓存等原因,每秒请求数波动很大。在 Web 群集中,设置一个公共写入区域可能会出现安全问题。硬盘设置也可能是一个问题,因为操作系统有点像数据库。如果您要测试此项,请密切关注创建的文件数量。

ODBC 会话提供程序:

我尝试让这个提供程序尽可能接近 Microsoft 示例,因此没有使用存储过程。它的性能不是很好。我尝试使用 Windows XP 上的 PostgreSQL 作为数据库。它每秒运行不到 20 个请求。我尝试使用 MS Access,它的性能也不是很好。这些结果让我很惊讶。

PostgreSQL 会话提供程序(无存储过程):

这个提供程序运行得相当好。在 5 个并发会话下,它大部分时间每秒运行 100 到 150 个请求。在 Web 服务器群中,我相信它可以处理更多每秒的请求。这个提供程序与 ODBC 会话提供程序非常接近,但它使用 PostgreSQL .NET 数据提供程序 Npgsql。

使用存储过程的 PostgreSQL 会话提供程序:

这个提供程序运行良好。在 5 个并发会话下,它大部分时间每秒运行 100 到 120 个请求。它为什么没有更好的性能,目前还是个谜。由于 ASP.NET 服务器和 PostgreSQL 服务器之间的流量较少,当 ASP.NET 和 PostgreSQL 在不同的服务器上时,它可能会比不使用存储过程的 PostgreSQL 会话提供程序表现更好。我确实将会话表规范化为两个表,一个用于存储会话项,另一个用于存储应用程序名称。我打算让存储会话项的表更小,表上的索引也更小,也许更有效率。我确信,在 Web 服务器场中,这个提供程序每秒可以处理更多的请求。

实验

起初,我以为 Microsoft 会使用一个带有静态方法的类。我还以为 Microsoft 会写出 Session State 提供程序需要如何管理线程问题。然而,我在文档中没有看到这一点。通过使用反射并遍历各种 System 类,Microsoft 似乎确实根据需要创建了提供程序的新实例,并将其存储一段时间。我的第一个想法是,“不可能”。于是,我创建了另一个提供程序,通过跟踪来测试,它确实似乎是根据需要创建了提供程序的新实例。ASP.NET 会根据需要重用已实例化的提供程序。

了解 ASP.NET 重用会话状态提供程序意味着我们可以寻找一些小方法来加快速度。一种加快速度的方法是限制复杂对象的创建,例如 Command 对象。目前,我已包含 PostgreSQLSessionSPCommon,它重用 Command 对象,但不重用连接。找到加快连接速度的方法将非常有帮助。然而,当前版本的 PostgreSQL .NET 数据提供程序 Npgsql 需要更多改进才能很好地实现这一点。我认为 Npgsql 在其下一个版本中将提供更好的连接管理支持。我们只能拭目以待。对于示例而言,根据负载和用户活动,重用命令对象可以带来不错的性能提升。

解决方案

该示例解决方案包含两个项目。SessionProviders 项目包含提供程序和依赖项。TestSessionProviders 项目是我用于测试的网站。默认页面有各种输入可放入会话状态。一个按钮将输入放入会话状态。默认页面上的另一个按钮从会话状态读取值并将其显示在屏幕上。另一个按钮优雅地关闭接收请求的服务器上的应用程序。默认页面上的一个链接将用户带到以只读模式读取会话状态的页面。只读页面有一个按钮用于检索会话状态中的值。默认页面上的另一个链接将用户带到不需要会话状态的页面。最后一个链接将用户带到使用帧且每个页面都需要读写模式的会话状态的页面。Web.config 中有一个针对每个提供程序的节;一次只能取消注释一个。由于提供程序使用连接字符串,因此有一个连接字符串节。您可能需要调整文本文件提供程序和 ODBC 无 DSN 连接字符串的路径到适当的位置。我在许多方法的开头放置了调试语句,以帮助观察正在发生的事情。如果您有用于在执行期间观察代码的工具,请使用它。在解决方案级别,有一个解决方案文件夹,其中包含用于在此处为提供程序设置 PostgreSQL 数据库的脚本。

结束语

好了,这里有一些会话状态提供程序供您试用。请对上述结果持保留态度,因为有许多因素会影响性能。希望在不久的将来,我会有机会看看 Npgsql 发生了什么。我确信下一个版本的 Windows 上的 PostgreSQL 将产生更好的结果。

如果您尝试示例 PostgreSQL 提供程序,您将需要安装 PostgreSQL 8.2.3 和 PostgreSQL .NET 数据提供程序 Npgsql。创建表和存储过程的 SQL 是 .NET 解决方案的一部分。您需要根据需要调整 SQL 以适应您的数据库。

历史

目前还没有。

© . All rights reserved.