【问题标题】:Dealing with huge traffic - online ticket website处理巨大的流量 - 在线票务网站
【发布时间】:2013-09-17 10:18:29
【问题描述】:

背景:

基于 Asp.net 4.0 的电子商务网站。托管在具有专用 SQL Server 2008 标准(16 核)和 32GB RAM 的云设置上。

用户交互:

  1. 用户访问网站。
  2. 浏览不同的类别(还没有静态内容)
  3. 将产品放入购物车
  4. 计时器最多计时 15 分钟。
  5. 结帐
  6. 登录/创建帐户
  7. 使用 Authorize.Net 网关处理付款(用户停留在我们的网站上)
  8. 使用第三方 SMTP 提供商在注册/忘记密码/订单完成时发送电子邮件。

注意:当产品页面加载和放入购物车时,会检查门票的可用性。一旦他们在购物车中有产品,肯定会有一个计时器计时 15 分钟。每 25 秒查询一次数据库以更新计时器。

事件:

好吧,伙计们,我们上周进行了一次大促销,可能为美国各地的粉丝出售了大约 10000 张门票。我们看到了无法控制的流量,在 2-4 小时内,我们看到我们网站上大约有 1000 名并发用户。

问题:

问题是我们有大约 6 个 2GB 的云服务器,这些服务器很快就被填满,然后由于巨大的流量而崩溃。然后我们必须启动 4gb、8gb 和 16gb 服务器(各 2 个)来处理流量。在大约 15-20 分钟的崩溃期间,网站变得无响应,我们还看到数据库(专用数据库)的 CPU 使用率达到 100%。

  • gb 是服务器的 RAM 容量。

框架:

.net 代码编写得非常高效,它只执行两个 SQL 语句来获取和构建需要在浏览器上呈现的所有必要数据。处理数据库的所有业务逻辑都写在存储过程中。没有游标,存储过程中没有动态sql。

必填:

  1. 我无法理解网站崩溃的原因...我实施了许多代码分析工具,它们不断告诉我们哪个代码部分花费了太长时间或哪个查询花费了太多时间。当我们拥有更大的服务器(8gb 或更多)时,网站运行顺畅。

  2. 我是否应该消除每次加载页面时都对数据库进行锤击的需要?比如拥有静态页面怎么样? (虽然它需要我们将产品信息导出到 html 中,这很好)。

  3. 如果我将页面存储在 Lucene.Net 索引中会怎样?然后从中渲染?在这种情况下,I/O 会花费很多吗?

我真的想要一些关于如何解决这个问题的专家意见?我们最初计划处理 25,000 个并发用户,但我们发现我们需要大量大型云服务器来处理这个问题。

谢谢

【问题讨论】:

  • 您使用的是哪个云提供商?您的基础架构是什么样的?你是如何处理负载平衡的?另外,主页上的内容多久更新一次?用户同时访问哪些页面?只是首页,还是有某些热门页面?
  • @Maz, rackspace, rackconnect firewall, f5 LB,内容仅在我们有新产品发售时更新,在销售期间完全没有变化。仅列出产品。所有产品都很受欢迎,客户大多对多种产品感兴趣。类别 > 产品 > 添加到购物车 > 结帐 > 登录 > 付款 > 接收电子邮件通知。我们正在使用第三方电子邮件提供商),实时库存处理,因此我们可以看到 mnay 门票的销售情况,在预订(在购物车/待付款中)和可用)库存实用程序每 10 秒运行一次以进行清理。购物车上的计时器会运行 15 分钟,以便有足够的时间完成。
  • 您的第一步可能是缓存查询。我建议使用 memcached (memcached.org)。 Memcached 是一种内存键值存储。使用 memcached 的想法是将您的查询过程变成en.wikipedia.org/wiki/Memcached#Example_code 这只是第一步,它可能会解决您的问题,也可能不会。您可能遇到的一个问题是 memcached 的问题code.google.com/p/memcached/wiki/…

标签: asp.net sql-server-2008 concurrency lucene.net high-traffic


【解决方案1】:

我是否应该消除每次加载页面时都对数据库进行锤击的需要? 比如拥有静态页面怎么样? (虽然它需要我们导出 将产品信息转换为 html 即可)。

您不需要将产品转换为 html 或任何第三方代码来执行此操作。 Asp.NET 内置了对输出缓存的支持。

网络表单:

<%@ OutputCache Duration="60" VaryByParam="none" %>

MVC:

[OutputCache(Duration=60, VaryByParam="none")]
public ActionResult Index()
{
    return View();
}

其中 Duration 是以秒为单位缓存页面的持续时间,而 VaryByParam 是充当该页面键的 url 参数。它将为提供的每个不同参数缓存页面,因此您通常不会为 index 和 ProductId 保留特定产品页面)

但您必须进一步调查,因为这可能不是您网站速度变慢的唯一原因。

【讨论】:

  • 那么它是否适用于在整个 Web 应用程序执行过程中动态加载的嵌套控件?
  • 不太确定我是否正确理解了您的问题。但是 AFAIK,只有最终的 html 输出被缓存。所以是的,它会缓存添加到页面的每个控件。
【解决方案2】:

您的查询是什么样的?您说业务逻辑在存储过程中,但您在这些过程中使用动态 sql、游标还是全文索引?都是CPU高的可能原因。

Lucene.NET 只能在您使用 sql 全文索引时提供帮助,在这种情况下,它已被证明更有效。但仅限于搜索是您的瓶颈的情况。

如@Andre 所述,缓存可以帮助流行页面并减少数据库负载,但请注意缓存命中/未命中率以及正在缓存的页面。例如,您将在“类别”和“产品”页面上物有所值,但最终会在用户特定的购物车页面上使用更多的内存而获得更少的收益(如果有的话)。

如果您要在那些热门页面上显示实时票务可用性,如果您访问数据库以获取该号码,这可能会对您造成很大伤害。如果是这种情况,请尝试增加这些更新的延迟并稍后在此过程中进行验证。

【讨论】:

  • 在加载产品页面和放入购物车时检查门票的可用性。一旦他们在购物车中有产品,肯定会有一个计时器计时 15 分钟。每 25 秒查询一次数据库以更新计时器。
  • 我们没有使用任何搜索。它从来不需要。访客进来,他们知道他们的目标产品,他们访问这些类别并选择他们的产品并购买。我提到了使用 lucene 来保存数据库中的命中以呈现产品信息,因为它将来自 lucene,并且搜索将由代码在内部执行。大约有20-30种产品。所以索引大小会非常小。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-25
  • 1970-01-01
  • 2011-04-30
  • 2012-01-20
  • 1970-01-01
  • 2010-10-31
相关资源
最近更新 更多