2016-01-22 27 views
2

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

如果多次请求来自同一个用户,默认情况下,ASPNET序列 的要求,我们可以在这个环节看,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面临很多difficults来inhertis的OutputCacheAttribute和they have rewritten it completely

在实施甜甜圈缓存方面,挂钩到 OutputCacheModule HttpModule将是非常困难/不可能的,所以 而不是我们必须重写OutputCacheAttribute comp letely

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

回答

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的缓存,这样的动作还是会触发多次。

+0

这是一个性能问题。无法预热缓存,因为该操作是基于Web资源和参数动态生成的。 – mqueirozcorreia

+0

我真的想要使用ActionFilter中的锁的想法,但并不希望在执行某个动作时锁定每个动作,而是使用UniqueId(考虑动作和参数)的特定锁,这就是为什么我想要使用'GetChildActionUniqueId'。 – mqueirozcorreia

+0

您可以将操作筛选器应用于具有其属性的特定操作。 – Cleverguy25