【问题标题】:ASP.NET MVC Session state using state partitioning, MongoDB or Memcached or...?ASP.NET MVC 会话状态使用状态分区、MongoDB 或 Memcached 还是...?
【发布时间】:2011-09-04 02:24:22
【问题描述】:

我的团队目前正在为我们公司 (Amilia.com) 构建一个新的 SaaS 应用程序。我们处于“alpha”版本,该应用程序是为部署在网络场上而构建的。

对于我们的会话提供者,我们使用 Sql Server 模式(在 DEV 和 TEST 中),它似乎不是“可扩展的”,因此我们正在寻找在 asp.net 中处理会话的最佳解决方案(在我们的例子中是 mvc3 )。我们目前正在使用 Sql Server,但由于许可成本,我们想切换到其他系统。

我们的目标是 20 000 [已编辑,之前是 10 万] 并发用户。在会话中,我们存储了一个 GUID、一个字符串和一个 Cart 对象(我们尽量减少它,这个对象允许我们在每次请求时保存 3 个查询)。

以下是我找到的不同解决方案:

ASP.NET 内置解决方案:

无会话:在我们的情况下是不可能的(已消除)

进程内模式:不能在网络农场中使用。 (消除)

StateServer 模式:可以在 webfarm 中使用,但如果服务器出现故障,我会丢失所有会话。 (消除)

带有 PartitionResolver 的 StateServer 模式使用多个服务器 (http://msdn.microsoft.com/en-ca/magazine/cc163730.aspx#S8) 如果我理解得很好,如果其中一个服务器出现故障,那么只有一部分用户会丢失他们的会话。

SqlServer 模式:可以在 webfarm 中使用,如果服务器出现故障,我可以恢复我的会话,但过程很慢。此外,在负载过重的情况下,该数据库会成为瓶颈。

具有使用多个服务器的 PartitionResolver 的 SqlServer 模式 (http://www.bulletproofideas.net/2011/01/true-scale-out-model-for-aspnet-session.html):如果其中一个服务器出现故障,我的用户中只有一部分会丢失他们的会话。如果用户在停机期间没有做任何事情,他将恢复他之前的会话,否则他将被重定向到登录屏幕。

自定义解决方案:

使用 MongoDB 作为 Session 存储 (http://www.adathedev.co.uk/2011/05/mongodb-aspnet-session-state-store.html) 这似乎是一个很好的折衷方案,但我对 nosql 的了解还很初级,所以我看不到缺点。

使用 Memcached :问题与 StateServer 模式相同,如果 memcached 服务器出现故障,我的所有会话都将丢失。此外,我认为 Memcached 并非专门用于存储会话状态?

使用像 ScaleOut (http://highscalability.com/product-scaleout-stateserver-memcached-steroids) 这样的分布式 memcached:似乎是最好的解决方案,但它需要花钱。

使用 repcached 和 memcached (http://repcached.lab.klab.org/),我从未见过该解决方案的实现。

我们可以很容易地去 Ms Azure 并使用它提供的工具,但我们只有一个应用程序,所以如果微软将价格翻倍,我们的基础设施成本就会立即翻倍(但这是另一个主题)。

那么,最好的方法是什么,或者至少您对此有何看法?

【问题讨论】:

    标签: asp.net-mvc performance session scalability


    【解决方案1】:

    SQL Server 会话非常好。由于您已经有一个 SQL Server 数据库来存储您的主要数据,您可以创建另一个数据库并将 ASP.NET 会话存储在那里。

    关于可扩展性,我会说如果您有 100,000 个并发用户,那么您的用户群必须超​​过 1000 万或更多。您应该做一些实际的估计,看看真正达到这样的并发用户负载需要多长时间。在我之前的创业公司中,我们在全球范围内拥有 24x7 全天候的数百万用户,但我们几乎没有达到 10K 的并发用户,即使人们每天连续使用我们的网站数小时。

    如果您真的有 100,000 个并发用户,那么您最不担心的就是许可成本。采用正确的商业模式,拥有 10 万并发用户意味着您每年至少有 1000 万美元的收入。

    我已经构建了 myoffice.bt.com,它使用 SQL Server 会话和单个 SQL Server 实例上的所有主要数据,但在两个数据库中。在上午 8 点到 10 点之间,数百万用户访问了我们的网站。我们几乎没有任何性能问题。使用双核服务器和 8 GB RAM,只要编码正确,您就可以愉快地运行 SQL Server 实例并支持这样的负载。这完全取决于您如何编码。如果您遵循了性能最佳实践,您可以轻松地在单个数据库服务器上扩展到数百万用户。

    看看我的性能建议: http://omaralzabir.com/tag/performance/

    我只使用 memcached 集群来缓存经常使用的数据。出于充分的理由,从未用于会话。有好几次必须重新启动 memcached 服务器的情况。如果我们将 memcached 用于会话,我们将丢失存储在该实例中的所有会话。因此,我不建议将会话存储在 memcached 中。但话又说回来,你的应用程序在会话中维护数据有多重要?如果您有一个购物车,那么当用户在购物车上添加产品时,它必须保存在数据库中,而不是会话中。会话通常用于短期存储。对于任何事务性数据,您都不应该将其保留在会话中,而应直接将其存储在关系表中。

    我一直支持不使用 Session。开发人员一直在滥用会话。每当他们想将数据从一个页面传递到另一个页面时,他们只需将其放在 Session 上。它导致糟糕的设计。如果您真的想扩展到 10 万并发用户群,请将您的应用设计为根本不使用会话。任何事务数据都必须存储在数据库中。 Cart 是一个事务性对象,因此它不适合持有 Session。在某些时候,您需要知道有多少购物车开始使用但从未被放置。因此,您需要将它们永久存储在数据库中。

    请记住,基于数据库的会话只不过是基于数据库的序列化。仔细考虑要序列化到数据库中的内容。您还必须清理它,因为 Session_End 不会为基于数据库的会话触发,或者实际上是大多数 out of proc 会话。因此,本质上,您让开发人员能够将数据序列化到数据库中并绕过关系模型。它总是导致糟糕的编码。

    使用永久关系存储,并以高性能缓存(如 memcached)为前端,您可以拥有更好的设计来支持庞大的用户群。

    希望这能帮助您解决问题。

    【讨论】:

    • 感谢您的回答,非常有趣。事实上,我们在未来 2 年的平台目标是 5000 个客户,每个客户大约有 300 个用户。对于每个客户,我们提供一个注册平台,我们所有客户的注册时间一般都在同一时间(=> peeks)。由于售出的商品在不到 5 分钟内就卖光了,因此很难估计“并发用户”的数量。通过阅读你,也许我高估了我们的目标。以 20K 并发用户为目标似乎更合理。对于会话,使用 Memcached 存储会话似乎很糟糕。
    • Between 8 AM to 10 AM, millions of users hit our site. We hardly have any performance issue. With a dual Core server, 8 GB RAM 真的是这样吗? :::O
    猜你喜欢
    • 1970-01-01
    • 2021-03-03
    • 1970-01-01
    • 1970-01-01
    • 2010-09-28
    • 2011-02-06
    • 2011-06-07
    • 2010-11-02
    • 1970-01-01
    相关资源
    最近更新 更多