应用程序级排队/网站流量管理

har*_*don 20 asp.net-mvc asp.net-mvc-3 asp.net-mvc-4

我们有一个网站应用程序,我们希望在全年的几个点上获得令人难以置信的高流量.我们目前有一些第三方负载平衡软件,可以在繁忙时段将用户重定向到"保留"页面,以防止我们的Web应用程序服务器被请求的数量所窒息.

展望未来,我们希望能够更好地控制此过程并实现某种虚拟队列.当前负载均衡器没有排队功能,但只允许基于速率限制的流量.这是随机的,当您刷新页面(或获得自动刷新)时,运气很好.

我已经在网上阅读了一些关于此的内容,但发现了很少有关如何实现非常基本的虚拟HTTP请求队列的实现细节.当然,公司提供这种服务作为一种完全成熟的服务,例如queue-itNetprecept,但这些服务对我们当前的需求来说似乎有些过分(并且非常昂贵).

有问题的Web应用程序是用ASP.Net MVC编写的.请记住,我们现在不需要诸如"队列优先级"等高级功能,我使用静态队列管理器类创建了一个非常基本的概念验证,ConcurrentQueue<T>但是我想知道这是否是一个有效,可扩展的方法?这是否可以成为主要应用层的一部分?还是应该分开?有没有人知道如何在ASP.Net MVC应用程序中实现这种功能?


编辑:感谢目前为止的答案.大多数答案似乎都涉及很多关于缓存的细节.这已经(非常)在我们的网站上大量使用,使用ASP.Net网络缓存,在负载均衡器级别缓存完整页面请求和使用AppFabric进行对象缓存.

能够管理队列的原因是因为该进程非常重要.我们通过网站有效地为某个产品创建订单.这意味着这些数据库事务正在考虑事项,例如最后一刻的库存检查等.这就是性能问题出现的地方,这就是想要实现某种排队系统的原因.

在数据库服务器上投入更多资源并不是一个现实的选择.我真的在寻找这种排队系统(C#或其他)的技术实现细节.对不起,如果最初没有说清楚.

Ima*_*ani 25

您是否在测量应用性能时考虑以下几点?

  1. 高速缓存
  2. 无会话控制器
  3. AsyncControllers

输出缓存:

也许MVC3(Performance-Wise)最有用的功能是输出缓存.当您的应用程序确实需要获取数据,对其进行计算并返回数据时,实际上会发生最大的性能命中.输出缓存可以缓存这些结果,因此可以直接返回它们,甚至无需触及数据库.特别是在执行复杂查询时,这会显着降低服务器上的负载(实际上,您可以通过在Web应用程序中仔细调整缓存来减少90%的服务器负载).

namespace MvcApplication1.Controllers
{
     public class DataController : Controller
     {
          [OutputCache(Duration=10)]
          public string Index()
          {
               return DateTime.Now.ToString("T");    
          }
     }
}
Run Code Online (Sandbox Code Playgroud)

无会话控制器:

禁用会话状态的控制器为不需要会话状态的控制器提供优化.无状态控制器适用于不需要会话概念的情况.

默认情况下,ASP.NET管道不会同时处理属于同一会话的请求.它将它们序列化,即它按照它们被接收的顺序对它们进行排队,以便它们被串行处理而不是并行处理.这意味着如果请求正在进行且来自同一会话的另一个请求到达,则它将排队等待仅在第一个请求完成时开始执行.

我们来看一个例子; 一个页面向服务器发出3个异步AJAX请求,启用了会话状态(还要注意,实际上必须使用会话,因为如果你从不使用会话状态,即使启用了会话状态,ASP.NET也足够聪明不会序列化请求).

JQuery的

$(document).ready(function () {
    //Make 3 concurrent requests to /ajaxtest/test
    for (var i = 0; i < 3; i++) {       
        $.post("/ajaxtest/test/" + i,
            function (data) {                       
                //Do something with data...
            },
            "json");
    }
});
Run Code Online (Sandbox Code Playgroud)

控制器 - 动作方法

public class AjaxTestController : Controller
{       
    [HttpPost]
    public JsonResult Test(int? id)
    {
        Thread.Sleep(500);
        return Json(/*Some object*/);
    }
}
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

您可以在网络配置文件中看到序列化请求的效果; 每个请求比前一个请求大约长500毫秒.所以这意味着我们没有从异步制作这些AJAX调用中获得任何好处.让我们再次查看配置文件,为AjaxTestController禁用会话状态(使用[SessionState]属性).

[SessionState(SessionStateBehavior.Disabled)]
public class AjaxTestController : Controller
{       
    //...As above
}
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

好多了!您可以看到3个请求是如何并行处理的,并且总共需要500毫秒才能完成,而不是我们在第一个示例中看到的1500毫秒.

异步控制器:

首先,控制器开始一个或多个外部I/O调用(例如,SQL数据库调用或Web服务调用).在不等待它们完成的情况下,它将线程释放回ASP.NET工作线程池,以便它可以处理其他请求.

稍后,当所有外部I/O调用完成后,底层ASP.NET平台从池中获取另一个空闲工作线程,将其重新连接到原始HTTP上下文,并让它完成处理原始请求.

在此输入图像描述

如何衡量交通繁忙时的响应时间?

我从这个链接复制了以下内容.因为某些时候链接被破坏所以我在这里保留了一些重要的部分.请查看此链接以获取更多详细信息

要了解异步控制器如何响应不同级别的流量,以及如何与简单的同步控制器进行比较,您可以创建一个带有两个控制器的示例MVC.为了模拟长时间运行的外部,它们都执行一个需要2秒才能完成的SQL查询(使用SQL命令WAITFOR DELAY '00:00:02')然后它们将相同的固定文本返回给浏览器.其中一个是同步的; 另一个是异步的.

在另一个示例中,您可以检查一个简单的C#控制台应用程序,该应用程序模拟大量流量命中给定的URL.它只是一遍又一遍地请求相同的URL,计算最后几个响应时间的滚动平均值.首先它只在一个线程上执行,但随后在30分钟内逐渐将并发线程数增加到150.如果您想尝试对自己的站点运行此工具,可以下载C#源代码.

结果说明了有关异步请求如何执行的许多要点.查看平均响应时间与并发请求数的图表(响应时间越短越好):

在此输入图像描述

要理解这一点,首先我需要告诉您,我已将ASP.NET MVC应用程序的工作线程池设置为人为的最大限制为50个工作线程.我的服务器实际上有一个默认的最大线程池大小200 - 一个更明智的限制 - 但如果我减少它的结果会更清楚.正如您所看到的,只要有足够的工作线程可以执行,同步和异步请求的执行完全相同.他们为什么不应该呢?但是一旦线程池耗尽(> 50个客户端),同步请求就必须形成一个要服务的队列.基本排队理论告诉我们,队列中等待的平均时间由公式给出:

在此输入图像描述

这正是我们在图中看到的.排队时间随着队列的长度线性增长.(为我放纵使用公式而道歉 - 有时候我无法抑制我的内心数学家.如果它成为一个问题,我会接受治疗.)异步请求不需要这么快就开始排队.它们不需要在等待时阻塞工作线程,因此线程池限制不是问题.那么,当有超过100个客户时,为什么他们会开始排队?这是因为ADO.NET连接池默认限制为100个并发连接.

希望这对你有帮助.


Ale*_*iuc 3

IIS 有自己的队列,您可以为每个应用程序池进行配置。这是包含有关性能的有用提示的链接。

我不建议混合应用程序代码和处理低技术性能优化的代码。将其分开,因为它将使您的代码易于维护。