OutputCache序列化并发请求

时间:2016-01-22 22:31:59

标签: c# asp.net asp.net-mvc multithreading caching

ASP.NET中的

OutputCache is an easy way to improve performance< = 4.6 MVC。我们应该将这些属性应用于非常昂贵的操作,但是在第一个请求和正在创建的缓存之间我们可能会有很多并发请求 - 并且会占用我们试图保护的服务器资源(内存,CPU,I / O)。

如果多个请求来自同一个用户,则默认情况下为aspnet serialize 我们可以在此链接中看到The Downsides of ASP.NET Server Sate

  

默认情况下,ASP.NET管道不会处理属于的请求   同时进行相同的会话。它将它们串行化,即它将它们排队   按照他们收到的顺序,以便他们被处理   串行而不是并行。

因此,为了模拟这种情况,我们需要创建多个请求(来自不同的用户)。可以通过从多个浏览器创建请求或使用具有多个线程的任何类型的工作负载来完成此操作。

因此,我尝试从OutputCacheAttribute继承并创建类似OutputCacheConcurrentRequestAttribute的内容,并序列化来自多个用户的请求。有没有人试过这样做?

当第一个请求未完成时,我们的想法是Thread.SleepOnActionExecuting上相同资源(由OutputCache属性和操作考虑唯一)的所有后续请求。

在ILSpy中查看IL,一些可以帮助我完成这项工作的方法是私有的和内部的,如下:

程序集:System.Web.Mvc

命名空间:System.Web.Mvc

class OutputCacheAttribute
{
private GetChildActionUniqueId
private BuildUniqueIdFromActionParameters
}

internal class DescriptorUtil

我试图不复制代码而不使用反射器(出于性能原因)。

有人遇到过同样的问题吗?

修改1

经过一些研究后我发现MVC Donut caching面临很多困难,包括OutputCacheAttribute和they have rewritten it completely

  

在实施甜甜圈缓存方面,挂钩   OutputCacheModule HttpModule将非常困难/不可能,所以   相反,我们必须完全重写OutputCacheAttribute

使用DonutOutputCacheAttribute完成我的想法要容易得多。

1 个答案:

答案 0 :(得分:1)

您是否真的将此视为性能问题或仅仅是理论上的问题?我要提醒的是,在这条路上走太远可能会影响性能...也许可以考虑一个预热缓存的解决方案?

那就是说,如果只是锁定你想要执行一次的动作,你可能会有更好的运气。创建一个变量,并在操作过滤器中对该变量进行锁定(在操作触发之前),并在操作触发后在操作过滤器中释放,并且应该序列化您的请求。

public class SerializedOutputCacheAttribute : OutputCacheAttribute
{
    private readonly object lockObject = new object();

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        Monitor.Enter(this.lockObject);
        base.OnActionExecuting(filterContext);
    }

    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        base.OnActionExecuted(filterContext);
        Monitor.Exit(this.lockObject);
    }
}

然后,您可以将其应用于任何操作,该操作将被序列化,但不会影响其他操作。

    [SerializedOutputCache(Duration = 5000)]
    public ActionResult About()

编辑:这种方法无法正常工作,因为OutputCacheAttribute实际上会推送到IIS进行缓存,因此操作仍会多次触发。