将大对象存储到InProc会话而不是在每个页面上重新加载

时间:2017-05-31 21:29:54

标签: asp.net

这是我的第一篇帖子/问题,所以请告诉我是否/如何改进它。我发现了类似的问题,但没有完全涵盖这一点。

当您存储到InProc会话时,您只是存储对数据的引用。所以,如果我有一个公共属性foo,并将它存储在Session(“foo”)= foo中,那么我还没有真正占用任何额外的内存(除了指针使用的32/64位)? / p>

在我的情况下,我们正在我们网站的每个页面上重新加载foo,所以如果我将其存储在会话中,那么它应该采用相同的空间,但不需要在每个页面上重新加载。我看到很多人说不会在会话中存储大对象,但是如果那个大对象已经存在,那么指向它的指针有什么区别?当然,我会在不再需要的时候从会话中删除该对象。

我们尝试存储的数据是特定于用户当前工作的对象,而不是用户数据。作为类比,假设用户是汽车经销商,他正在查看特定客户的所有数据。我们为这个客户提供了多个页面,我们希望在每个页面上保存所有客户信息,所有客户数据都存储在SQL表中的单个xml数据列中,我们在每个页面上进行解析。

我们尝试过二进制序列化而不是解析xml,因此我们可以在状态服务器模式下存储会话,但我们发现性能实际上更差。

我们正在一台网络服务器上运行。

1 个答案:

答案 0 :(得分:0)

首先,没有。当您在会话状态中存储某些内容时,网站进程将使用存储该对象所需的所有数据。仅仅因为.NET将变量视为引用并不意味着它实际上使用的内存少于无GC语言。它只是意味着在不使用引用运算符或指针的情况下有效地复制该变量。

您的问题有点模糊,但您可以选择保留数据:

1)将数据作为JSON发送到客户端并将其存储在浏览器中(如果它应该是每个用户的,并且在客户端比服务器端需要更多)。然后,如果需要,您可以使用不同的请求发送数据(如果必须使用ASPX Web表单,则将其放在隐藏字段中)。

2)如果它是每个用户数据的一小部分,则将其存储在会话状态中。

3)如果它很大并且对所有用户都通用,则将其存储在ASP.NET缓存中,请参阅此处(https://msdn.microsoft.com/en-us/library/6hbbsfk6.aspx)。

4)如果它主要在服务器上使用且很大且特定于用户,则会出现更多性能问题。您应该看看是否可以从静态内容中删除任何特定于用户的内容。如果你这样做并且它仍然很大,那么数据库可能不是一个糟糕的解决方案。如果您已经在应用程序中使用数据库调用,那么在每个请求中查找此数据不会产生太多开销,您也不必从头开始重新生成(只有在数据需要相当长的时间才能执行此操作时生成数据库调用可能比仅重新生成数据本身要慢。我建议编写某种中间件(HttpModule或OwinMiddleware),它使用您用于身份验证的任何用户身份来查找数据,然后在HttpContext.Current.Items集合上设置它。这样,数据可用于整个请求,您可以在中间件中添加逻辑以确定何时设置它。

我认为拥有大量特定于用户的数据将是一个红旗,因为用户数据应该只是用户可以/不能做什么以及他们的偏好是什么的列表。

如果这是静态数据则其超级简单。应用程序缓存是您想要的。唯一的复杂情况是,如果您有多个需要同步数据的服务器。