【问题标题】:ASP.Net Persisting ObjectsASP.Net 持久化对象
【发布时间】:2009-12-22 19:09:05
【问题描述】:

我正在构建一个 ASP.Net 网站。我有一个“购物车”类,它将物品存储在用户购物车中。我不想每次重新加载页面以填充存储在此对象中的购物车项目时都重新查询数据库。通过将实例化对象放入会话并将会话存储到数据库(我们在 SQL Server 2k8 上)来存储/持久化实例化对象的最佳方法是什么?这似乎是大多数人在阅读 StackOverflow 上的其他帖子时所推荐的。我们的网站流量非常大,因此很容易想象在任何给定时间都有 1000 多个这样的对象处于活动状态。

我是构建 ASP.Net 网站的新手。持久化用户对象(不仅仅是会话或 cookie 中的简单变量,还有类对象)是常见的做法吗......也沿着持久化对象的路线,我计划创建一个静态类来存储常用的站点范围数据,例如作为美国各州列表......这样做有什么陷阱吗?我不想在脚上开枪。

更新:

我们处于农场环境中,因此将会话存储在数据库中似乎是不可能的……如果一台服务器出现故障,我们将切换到另一台服务器……在这种情况下,会话数据可能会丢失。我们正在考虑使用单独的服务器来存储会话,这将在我们的农场环境中工作,但我对将这么多实例化的对象存储在内存中感到不确定。

【问题讨论】:

    标签: .net asp.net static persistence


    【解决方案1】:

    会话可能是您的最佳选择。

    由于您使用 SQL 作为您的会话持有者,它将不在进程中,因此您可以毫无问题地在网络场上使用它。但是,每次引用该对象时,您仍然会遇到数据库命中。但是,它是一种高效的数据库命中。

    请务必确保您的 Cart 类是“可序列化”的,否则它会在进入 Session 时崩溃。

    【讨论】:

    • 这本质上是 NHibernate 所做的吗? hibernate.org/343.html ... 有人会推荐它作为固体产品吗?
    • 我会添加更多内容以确保您理解。是的,如果您的会话服务器出现故障,您将丢失所有会话数据。它与数据库服务器非常相似。您可以添加一个数据库(那里有一个脚本)来为您保存会话数据。它可以在自己的服务器上,也可以与您的应用程序数据的其余部分在同一台服务器上。
    • 我没用过NHibernate,所以无法评论。
    【解决方案2】:

    您可能需要考虑研究一种新的 Microsoft 技术,他们称之为 AppFabric。它包含分布式缓存功能(以前称为 Velocity)。当然,将会话状态持久化到 SQL 的问题在于,每次访问会话状态时都会命中数据库。当然,使用 Session 对象的问题是它仅可用于在农场环境中发生故障的特定服务器。 Velocity 提供了一个分布式缓存(它也能够与 ASP.NET 会话数据相当无缝地工作),它是一个分布在一些机器上的内存缓存,您的所有服务器都可以访问它。

    【讨论】:

    • 嗯嗯,这很好回答...我们确实有一个农场环境,因此将数据存储在 sql server 中似乎是不可能的。我正在与一位同事讨论这个问题,我们正在考虑使用单独的服务器来处理会话(没有数据库)......我会担心内存分配,因为我们会在那里为每个用户存储多个对象。我来看看 AppFabric
    • 不,我相信 sql 是在农场环境中存储会话数据的标准。使用 SQL 中的数据,可以从农场中的任何机器访问它。但是,每当您需要获取会话数据时,都会产生数据库命中的开销。
    • 在 SQL Server 中的存储已超出进程,因此您在网络场上没有任何问题。这正是它的设计目的。如果您想要一个单独的服务器来处理没有数据库的会话,那么您需要一个“StateServer”,它也在进程之外并且在网络场上工作得很好。
    • 这实际上可能是您更好的起点,因为我认为启动和运行可能会更快。使用单独的服务器来存储会话状态也是一种可能 - 但该解决方案不能很好地扩展。我对 AppFabric 了解不多——我自己才刚刚开始研究它——但我认为从长远来看它可能是一个更好的解决方案,因为它将状态推送到内存中,它是可扩展的,并且它是可访问的网络请求发生在哪台机器上。
    【解决方案3】:

    既然您说您不想在每次加载页面时都重新查询数据库,那么会话状态将是一个糟糕的选择——因为这正是它所做的(假设您使用的是 SQL 模式,因为 InProc 模式胜出不适用于网络农场)。实际上,每个请求通常有两次到数据库的往返:一次在开始时读取会话对象并更新会话到期时间,另一次在结束时更新它。会话还会在您的页面处于活动状态时对其施加锁定,这对于使用 Ajax 或框架或用户经常使用多个窗口的网站来说可能是一个问题。

    一般来说,从性能和可伸缩性的角度来看,您自己将对象存储在 SQL Server 中会更好。使用这种方法,您可以使用SqlDependencySqlCacheDependency 来缓存对象以避免往返。在网络场中,使用 cookie 来帮助确保一切同步通常也很有帮助,因为从更新数据库到通过通知清除所有服务器上的缓存条目可能会有一点延迟。

    如果有帮助,我会在我的书中详细介绍这些类型的问题:Ultra-Fast ASP.NET

    【讨论】:

      【解决方案4】:

      这可能是过早优化的情况。

      在我看来,如果您围绕使用会话状态进行设计,就很难创建一个高质量的网站。 HTTP 是“无状态的”,尽管有一些抽象设计来掩盖这一事实(例如 ASP.NET 会话),但您经常会遇到事实。 Session 对象是进行内存缓存的好工具,但你永远不应该指望它是可靠的。换句话说,您可以使用它来优化代码,但您仍然总是需要代码来执行完整的数据库检索作为后备。

      Session 的 In-SQL 存储是一种尝试解决服务器场问题的方法,但如果您一开始就试图避免使用数据库,为什么还要这样做呢?请记住,尽管您可能会跨请求重复查询相同的购物车数据,但 SQL 服务器本身可以为您完成大量缓存和优化。它可能没有你想象的那么慢。

      就静态数据而言,请谨慎使用。应用程序池回收有时会破坏内存中的数据,您必须非常小心,对需要启动初始化的静态数据的访问是可重入的。

      【讨论】:

        【解决方案5】:

        您能否在您的网络农场中使用粘性会话(亲和性),并将内容粘贴到会话中?

        http://msdn.microsoft.com/en-us/magazine/cc163844.aspx

        【讨论】:

        • 粘性会话是一个坏主意。它们严重干扰了可扩展性、可预测性和容量规划等方面,同时还消除了网络场的一项功能,即一台服务器在不中断用户的情况下发生故障的能力。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-01-21
        • 1970-01-01
        • 1970-01-01
        • 2017-10-10
        • 2015-09-30
        • 2015-01-06
        相关资源
        最近更新 更多