【问题标题】:Detect if Web API request is served by cache检测 Web API 请求是否由缓存服务
【发布时间】:2016-05-13 15:33:10
【问题描述】:

我们有一个使用 Strathweb.CacheOutput.WebApi2 进行缓存的 Web API 2 应用程序。

简短的问题:有没有办法在Application_LogRequest(或任何地方,真的)检测请求是否由缓存服务?

长问题: 最近,我们一直在关注性能,看看我们可以改进哪些 API 调用。我从我们的日志中提取了一个列表(包括持续时间),以查看最严重的违规者是什么。最严重的违规者是指最长的平均持续时间和/或最多的通话次数。

但这些数字具有误导性,因为缓存的请求包含在统计信息中。缓存请求通常在半秒或更短的时间内提供服务,因此它们会降低平均持续时间。另外,如果一个特定的调用被打了,比如说每分钟 1000 次,但其中 999 个被缓存了,我真的不在乎。

所以我想在我的日志中添加一个标志,指示请求是否由缓存提供服务,这样我就可以排除这些。我们所有的日志记录都是在 Application_LogRequest 事件中完成的。但即使我可以在其他地方检测到它,我也可以在 HttpContext.Current.Items 中存储一个值,以便以后检索。

【问题讨论】:

    标签: asp.net asp.net-web-api2 outputcache


    【解决方案1】:

    Strathweb CacheOutputAttribute 不会在 http 响应或其他地方添加一些可靠信息,以允许知道响应是否来自缓存。

    您可以从中派生出这样做,然后将您对 CacheOutputAttribute 的所有用法替换为您自己的。

    [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
    public class YourCustomizedCacheOutputAttribute : CacheOutputAttribute
    {
        public override void OnActionExecuting(HttpActionContext actionContext)
        {
            base.OnActionExecuting(actionContext);
            // If response is set, it has been retrieved from cache.
            actionContext.Request.Properties["yourCacheHitKey"] = 
                actionContext.Response != null;
        }
    }
    

    当然,如果您无法访问它,请使用 HttpRequestMessage.Properties 以外的其他内容。

    您可以通过示例添加一些自定义标头作为响应,如果将其泄露给浏览器对您来说不是问题:

    [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
    public class YourCustomizedCacheOutputAttribute : CacheOutputAttribute
    {
        // "X-" prefix is deprecated, but the rational behind this is about wannabe
        // standard header. I do not intend this one to become standard for anything.
        private const string _cacheHeader = "X-Cache";
        protected override void ApplyCacheHeaders(HttpResponseMessage response,
            CacheTime cacheTime)
        {
            base.ApplyCacheHeaders(response, cacheTime);
    
            if (response.Headers.Contains(_cacheHeader))
                return;
    
            // At this point, we do not know. miss by default.
            response.Headers.Add(_cacheHeader, "miss");
        }
    
        public override void OnActionExecuting(HttpActionContext actionContext)
        {
            base.OnActionExecuting(actionContext);
            if (actionContext.Response == null)
                return;
    
            // Response has been retrieved from cache.
            // Headers.Remove does not fail if not already there.
            response.Headers.Remove(_cacheHeader);
            actionContext.Response.Headers.Add(_cacheHeader, "hit");
        }
    }
    

    【讨论】:

    • 谢谢!我希望有一种不需要覆盖任何东西的方法,但看起来不可能。感谢您的示例代码。这肯定会有所帮助!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-30
    • 1970-01-01
    • 1970-01-01
    • 2023-03-17
    • 1970-01-01
    • 2012-12-29
    相关资源
    最近更新 更多