更改 ASP.NET 缓存项过期的频率?
Posted
技术标签:
【中文标题】更改 ASP.NET 缓存项过期的频率?【英文标题】:Changing frequency of ASP.NET cache item expiration? 【发布时间】:2010-09-21 01:46:35 【问题描述】:我注意到 ASP.NET 缓存项每 20 秒检查一次(并且可能会被删除)(奇怪的是每次都在 HH:MM:00、HH:MM:20 和 HH:MM:40)。我花了大约 15 分钟寻找如何更改此参数,但没有成功。我还尝试在 web.config 中设置以下内容,但没有帮助:
<cache privateBytesPollTime="00:00:05" />
我并不想做任何疯狂的事情,但是如果它是 5 秒而不是 20 秒,或者对于我的应用程序来说至少是 10 秒,那就太好了。
【问题讨论】:
【参考方案1】:使用 Reflector 进行探索发现间隔是硬编码的。过期由内部CacheExpires
类处理,其静态构造函数包含
_tsPerBucket = new TimeSpan(0, 0, 20);
_tsPerBucket
是readonly
,所以以后不能有任何配置设置修改它。
然后在CacheExpires.EnableExpirationTimer()
...中设置将触发检查过期项目的计时器...
DateTime utcNow = DateTime.UtcNow;
TimeSpan span = _tsPerBucket - new TimeSpan(utcNow.Ticks % _tsPerBucket.Ticks);
this._timer = new Timer(new TimerCallback(this.TimerCallback), null,
span.Ticks / 0x2710L, _tsPerBucket.Ticks / 0x2710L);
span
的计算确保计时器准确地在 :00、:20、:40 秒触发,但我看不出有任何打扰的理由。定时器调用的方法是internal
,所以我认为没有办法设置自己的定时器来更频繁地调用它(忽略反射)。
不过,好消息是您不应该真的有任何理由关心间隔。 Cache.Get()
检查项目是否过期,如果过期则立即从缓存中删除项目并返回 null
。因此,您永远不会从缓存中获取过期项目,即使过期项目可能会在缓存中停留长达 20 秒。
【讨论】:
【参考方案2】:根据documentation,privateBytesPollTime 用于“工作进程内存使用”,默认为 1 秒。我认为这与缓存项删除无关。
我确实使用项目删除回调确认了您的结果 - 看起来项目在分钟的底部、:20 和 :40 秒被删除。这表明项目可能会在缓存中保留长达 20 秒,超过对它们设置的 AbsoluteExpiration。我找不到任何说明是否可以更改 20 秒轮询间隔的文档。
【讨论】:
【参考方案3】:疯狂但有效的解决方案(需要所有步骤):
// New value for cache expiration cycle
// System.Web.Caching.CacheExpires._tsPerBucket;
// Set 1 seconds instead of 20sec
const string assembly = "System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
var type = Type.GetType("System.Web.Caching.CacheExpires, " + assembly, true, true);
var field = type.GetField("_tsPerBucket", BindingFlags.Static | BindingFlags.NonPublic);
field.SetValue(null, TimeSpan.FromSeconds(1));
// Recreate cache
// HttpRuntime._theRuntime._cacheInternal = null;
// HttpRuntime._theRuntime._cachePublic = null;
type = typeof (HttpRuntime);
field = type.GetField("_theRuntime", BindingFlags.Static | BindingFlags.NonPublic);
var runtime = field.GetValue(null);
field = type.GetField("_cachePublic", BindingFlags.NonPublic | BindingFlags.Instance);
field.SetValue(runtime, null);
field = type.GetField("_cacheInternal", BindingFlags.NonPublic | BindingFlags.Instance);
field.SetValue(runtime, null);
【讨论】:
以上是关于更改 ASP.NET 缓存项过期的频率?的主要内容,如果未能解决你的问题,请参考以下文章
实现自定义 CacheDependency 以使 ASP.Net 缓存项无效
.Net Core MemoryCache PostEvictionCallback 无法正常工作