检测缓存是否为 Web API 请求提供服务
Detect if Web API request is served by cache
我们有一个 Web API 2 应用程序正在使用 Strathweb.CacheOutput.WebApi2 进行缓存。
简短的问题:有没有办法在Application_LogRequest(或任何地方,真的)中检测请求是否由缓存提供服务?
长问题:
最近,我们一直在关注性能,看看我们可以改进哪些 API 调用。我从我们的日志中提取了一个列表(包括持续时间)以查看最严重的违规者是什么。最严重的违规者,我的意思是平均持续时间最长 and/or 呼叫次数最多。
但是这些数字具有误导性,因为缓存的请求包含在统计信息中。缓存的请求通常在半秒或更短时间内得到处理,因此它们拉低了平均持续时间。此外,如果正在进行特定调用,比如每分钟 1000 次,但其中 999 次被缓存,我并不在乎。
所以我想在我的日志中添加一个标志,指示请求是否由缓存提供服务,这样我就可以排除那些。我们所有的日志记录都在 Application_LogRequest 事件中完成。但即使我可以在其他地方检测到它,我也可以在 HttpContext.Current.Items
中存储一个值,以后可以检索。
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
以外的其他内容。
您可以通过示例添加一些自定义 header 作为响应,如果将其泄露给浏览器对您来说不是问题:
[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");
}
}
我们有一个 Web API 2 应用程序正在使用 Strathweb.CacheOutput.WebApi2 进行缓存。
简短的问题:有没有办法在Application_LogRequest(或任何地方,真的)中检测请求是否由缓存提供服务?
长问题: 最近,我们一直在关注性能,看看我们可以改进哪些 API 调用。我从我们的日志中提取了一个列表(包括持续时间)以查看最严重的违规者是什么。最严重的违规者,我的意思是平均持续时间最长 and/or 呼叫次数最多。
但是这些数字具有误导性,因为缓存的请求包含在统计信息中。缓存的请求通常在半秒或更短时间内得到处理,因此它们拉低了平均持续时间。此外,如果正在进行特定调用,比如每分钟 1000 次,但其中 999 次被缓存,我并不在乎。
所以我想在我的日志中添加一个标志,指示请求是否由缓存提供服务,这样我就可以排除那些。我们所有的日志记录都在 Application_LogRequest 事件中完成。但即使我可以在其他地方检测到它,我也可以在 HttpContext.Current.Items
中存储一个值,以后可以检索。
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
以外的其他内容。
您可以通过示例添加一些自定义 header 作为响应,如果将其泄露给浏览器对您来说不是问题:
[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");
}
}