C# IMemoryCache部署至测试IIS环境后永久缓存不生效问题
IMemoryCache在IIS部署后短时间失效问题解答
关于IMemoryCache的永久缓存能力
IMemoryCache是进程内内存缓存组件,不具备跨进程持久化能力,但只要宿主进程持续存活、未触发内存强制驱逐,按照给出的配置(CacheItemPriority.NeverRemove+6个月绝对过期+180天滑动过期),缓存项可以长期留存,本地调试时缓存能稳定持有6小时以上已经验证了配置本身的正确性。
IIS部署后缓存不足30分钟失效的核心原因
这个问题和IMemoryCache配置无关,完全是IIS应用程序池的默认进程回收规则导致的——IMemoryCache的存储完全绑定应用工作进程(w3wp.exe),一旦进程被IIS终止,内存中所有缓存数据会被直接清空,和设置的缓存过期规则没有任何关系。
默认配置下两个规则直接匹配故障现象:
- 应用程序池默认空闲超时为20分钟:如果连续20分钟没有请求进入应用,IIS会直接终止w3wp工作进程释放内存,等下一次请求到来时再重新启动进程。算上进程启动、缓存重新加载的耗时,刚好对应观察到的缓存生效不足30分钟的现象。
- 应用程序池默认开启内存阈值回收:单份缓存数据就超过5GB,加上应用运行本身的内存占用,很容易触发IIS默认配置的私有内存/虚拟内存回收阈值,触发IIS主动回收工作进程清空内存。
除此之外,IIS默认还开启了每1740分钟(29小时)的固定间隔回收,同样会清空内存缓存,只是这个规则不会导致30分钟级别的失效。
修复配置操作
按以下步骤调整对应应用程序池的高级设置,打开路径为:IIS管理器 -> 应用程序池 -> 选中对应站点的池 -> 右键「高级设置」:
- 关闭空闲超时回收
- 将
进程模型 -> 空闲超时(分钟)的值从默认20修改为0,即关闭无请求时自动终止进程的规则
- 将
- 关闭内存阈值回收
- 将
回收 -> 虚拟内存限制(KB)、回收 -> 专用内存限制(KB)的值都修改为0,关闭基于内存占用的进程回收。调整前需确认服务器剩余内存足够承载5GB以上缓存+应用运行开销,避免服务器内存不足导致崩溃。
- 将
- 调整固定周期回收规则
- 将
回收 -> 固定时间间隔(分钟)的值从默认1740修改为0,关闭默认29小时的自动回收。如果需要定期重启进程释放内存碎片,可以配置在业务低峰的固定时间点触发回收,不要使用无规律的固定间隔回收。
- 将
- 托管配置校验
- 确认应用程序池的
.NET CLR版本设置为无托管代码,同时服务器已安装对应版本的.NET Hosting Bundle,避免不必要的运行时干扰。
- 确认应用程序池的
补充提示:由于IMemoryCache完全依赖进程存活,只要出现服务器重启、应用崩溃、手动回收进程的操作,缓存都会全部丢失。如果需要避免进程重启后6分钟的加载耗时,要么在应用启动逻辑中加入缓存预热,要么更换支持持久化的分布式缓存方案存储这部分数据。
问题中给出的缓存配置代码本身没有逻辑问题,配置规则参考如下:
//Simplify class using using Microsoft.Extensions.Caching.Memory; //Simplify class var. private readonly IMemoryCache _memoryCache; //Simplify class constructor public GroupLoader(IMemoryCache memoryCache) { _memoryCache = memoryCache; } // Store to CACHE var cacheExpiryOptions = new MemoryCacheEntryOptions { AbsoluteExpiration = DateTime.Now.AddMonths(6), Priority = CacheItemPriority.NeverRemove, SlidingExpiration = TimeSpan.FromDays(180) }; _memoryCache.Set(cacheKey, data, cacheExpiryOptions);
内容的提问来源于stack exchange,提问作者Jan Sršeň
相关产品推荐
相关产品推荐

