【问题标题】:Changing frequency of ASP.NET cache item expiration?更改 ASP.NET 缓存项过期的频率?
【发布时间】: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 秒,那就太好了。

【问题讨论】:

    标签: asp.net caching


    【解决方案1】:

    使用 Reflector 进行探索发现间隔是硬编码的。过期由内部CacheExpires 类处理,其静态构造函数包含

    _tsPerBucket = new TimeSpan(0, 0, 20);
    

    _tsPerBucketreadonly,所以以后不能有任何配置设置修改它。

    然后在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);
        

        【讨论】:

          猜你喜欢
          • 2010-11-28
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-09-27
          相关资源
          最近更新 更多