我的团队目前正在为我们的公司(Amilia.com)构建一个新的SaaS应用程序。我们处于“alpha”版本,应用程序已构建为部署在Web场中。
对于我们的会话提供程序,我们使用的是Sql Server模式(在DEV和TEST中)并且它似乎不是“可伸缩的”,因此我们正在寻找在asp.net中处理会话的最佳解决方案(在我们的案例中为mvc3) )。我们目前正在使用Sql Server,但由于许可证成本,我们希望切换到其他系统。
我们的目标是20 000 [EDITED,之前是100k]并发用户。在会话中,我们存储GUID,字符串和Cart对象(我们尝试尽可能少地保留它,这个对象允许我们在每个请求时保存3个查询)。
以下是我找到的不同解决方案:
ASP.NET内置解决方案:
没有会话:在我们的情况下是不可能的(已消除)
进行中模式:不能在webfarm中使用。 (消除)
StateServer Mode:可以在webfarm中使用,但如果服务器出现故障,我会丢失所有会话。 (消除)
使用多个服务器(http://msdn.microsoft.com/en-ca/magazine/cc163730.aspx#S8)的PartitionResolver的StateServer模式如果我看不清楚,如果其中一个服务器出现故障,只有部分用户会丢失会话。
SqlServer Mode:可以在webfarm中使用,如果服务器出现故障,我可以恢复我的会话,但过程非常慢。而且,在负载很重的情况下,该数据库成为瓶颈。
使用多个服务器(http://www.bulletproofideas.net/2011/01/true-scale-out-model-for-aspnet-session.html)的PartitionResolver的SqlServer模式:如果其中一个服务器出现故障,只有部分用户会丢失会话。如果用户在停机期间没有做任何事情,他将恢复他之前的会话,否则他将被重定向到登录屏幕。
自定义解决方案:
使用MongoDB作为会话存储(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/),我从未见过该解决方案的实现。
我们很容易找到Azure女士并使用它提供的工具,但我们只有一个应用程序,所以如果微软的价格翻倍,我们会立即加倍我们的基础设施成本(但这是另一个主题)。
那么,最好的方法是什么,或者至少你对此有什么看法?
答案 0 :(得分:31)
SQL Server会话非常好。由于您已经有一个SQL Server数据库来存储主数据,因此您可以创建另一个数据库并在那里存储ASP.NET会话。
关于可扩展性,我想如果您有100,000个并发用户,那么您的用户群必须超过1000万或更多。您应该做一些实际的估计,看看到达这样的并发用户负载需要多长时间。在我之前的创业公司中,我们全世界有数百万用户,全天候,但我们几乎没有达到10K并发用户,即使人们每天连续使用我们的网站几个小时。
如果您确实拥有100,000个并发用户,那么许可证费用将是您最不担心的。使用正确的商业模式,拥有100K并发用户意味着您每年至少有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上。这会导致糟糕的设计。如果您真的想要扩展到100K并发用户群,请将您的应用设计为根本不使用会话。任何事务数据都必须存储在数据库中。 Cart是一个事务对象,因此它不适合持有Session。在某些时候,你需要知道有多少推车开始但从未放置。因此,您需要将它们永久存储在数据库中。
请记住,基于数据库的会话只不过是基于数据库的序列化。仔细考虑您要序列化到数据库中的内容。您必须清理它,因为Session_End不会触发基于数据库的会话或实际上大多数的proc会话。因此,基本上您可以让开发人员将数据序列化到数据库并绕过关系模型。它总是会导致编码错误。
使用永久关系存储,面向memcached这样的高性能缓存,你有更好的设计来支持庞大的用户群。
希望这可以帮助您解决问题。