.Net(windows服务器)清理缓存数据的几个方法
前言:最近在项目里将一批不常改变的数据做了缓存,但是一旦改变时需要立即更新缓存,针对此需求,开始接触清理缓存的研究,截止到目前,已经找到好几种方法了,供大家参考: ? 1-(手动)使用IIS应用程序池,手动回收; 2-(手动)如果应用程序池配置的:发生配置更改时禁止回收,的值是默认值False的话,可以通过修改应用配置文件:web.config; 3-(自动)使用代码回收应用程序池,借助ServerManager管理类实现。参照下面代码示例; 4-(自动、推荐)使用HttpRuntime.Cache缓存的机制清理,通过Cache.Remove清理指定缓存Key,也可以通过缓存依赖文件的机制通过修改缓存依赖文件来间接清理的办法; ? 其中前两种都是手动清理的方案,只能用于临时使用。? ?(核武器) 长久的办法还是推荐3和4,其中3属于整个应用的缓存全部回收了,这个一般情况下也不建议使用,除非整个项目更新可以。? (核武器) 方案4是重点推荐的方案,可以达到点对点清理或者清理依赖特定缓存文件的缓存数据。? (跟巡航导弹类似,指哪打哪) ? 方案三的代码如下,摘抄老师的源码: /// <summary> /// IIS应用程序池辅助类 </summary> public class IISManagerHelper { #region IIS 元数据库和IIS 6配置兼容性 private const string HOST = "localhost"; <summary> 取得所有应用程序池 要解决这个问题就得安装“IIS 元数据库和IIS 6配置兼容性”。 “控制面板”->“程序和功能”->面板左侧“打开或关闭windows功能”->“Internet信息服务”->“Web管理工具”->“IIS 6管理兼容性”->“IIS 元数据库和IIS 6配置兼容性”。 </summary> <returns></returns> [System.Obsolete(IIS 元数据库和IIS 6配置兼容性)] static List<string> GetAppPools_IIS6() { DirectoryEntry appPools = new DirectoryEntry(string.Format(IIS://{0}/W3SVC/AppPools,HOST)); return (from DirectoryEntry entry in appPools.Children select entry.Name).ToList(); } [System.Obsolete(static PropertyCollection GetAppPoolProperties_IIS6(string appPoolName) { PropertyCollection propertyCollection = null; DirectoryEntry appPools = foreach (DirectoryEntry entry in appPools.Children) { if (entry.Name == appPoolName) { propertyCollection = entry.Properties; } } return propertyCollection; } 获取应用程序数量 <param name="appName"></param> static int GetAppNumber_IIS6( appName) { int appNumber; Hashtable hashTable = new Hashtable(); List<string> poolList = GetAppPools_IIS6(); //获取应用程序池名称数组 foreach (string i in poolList) 填充哈希表key值内容 { hashTable.Add(i,""); } GetPoolWeb_IIS6(); Dictionary<string,int> dic = new Dictionary<int>(); poolList) { appNumber = hashTable[i].ToString() != "" ? Convert.ToInt32(hashTable[i].ToString().Split('').Length.ToString()) : 0; dic.Add(i,appNumber); } dic.TryGetValue(appName,out appNumber); appNumber; } 获取IIS版本 GetIisVersion_IIS6() { string version = .Empty; try { DirectoryEntry getEntity = new DirectoryEntry(IIS://LOCALHOST/W3SVC/INFO); version = getEntity.Properties[MajorIISVersionNumber].Value.ToString(); } catch (Exception se) { 说明一点:IIS5.0中没有(int)entry.Properties["MajorIISVersionNumber"].Value;属性,将抛出异常 证明版本为 5.0 } version; } 判断程序池是否存在 <param name="appPoolName">程序池名称</param> <returns>true存在 false不存在</returns> [System.Obsolete(bool IsAppPoolExsit_IIS6( appPoolName) { bool result = falseif (!entry.Name.Equals(appPoolName)) continue; result = true; break; } result; } 创建应用程序池 <param name="appPool"></param> bool CreateAppPool_IIS6( appPool) { { if (!IsAppPoolExsit_IIS6(appPool)) { DirectoryEntry appPools = IIsApplicationPool); entry.CommitChanges(); return ; } } ; } 操作应用程序池 <param name="appPoolName"></param> <param name="method">Start==启动 Recycle==回收 Stop==停止bool DoAppPool_IIS6(string appPoolName,1)"> method) { ; { DirectoryEntry appPools = ); findPool.Invoke(method,1)">); appPools.CommitChanges(); appPools.Close(); result = (Exception) { result = 删除指定程序池 true删除成功 false删除失败bool DeleteAppPool_IIS6( { entry.DeleteTree(); result = ; ; } { result = 获得所有的应用程序池和对应站点 </summary> [System.Obsolete(void GetPoolWeb_IIS6() { Hashtable hashTable = ); } DirectoryEntry root = IIS://localhost/W3SVC); foreach (DirectoryEntry website root.Children) { if (website.SchemaClassName != IIsWebServer") string comment = website.Properties[ServerComment"][].ToString(); DirectoryEntry siteVDir = website.Children.Find(Root",1)">IISWebVirtualDir); string poolname = siteVDir.Properties[AppPoolId].ToString().Trim(); if (.IsNullOrWhiteSpace(poolname)) { poolname = website.Properties[].ToString().Trim(); } poolList) { if (i != poolname) if (hashTable[i].ToString() == ) hashTable[i] = comment; else hashTable[i] += " + comment; } } root.Close(); } #endregion #region IIS7 取得所有应用程序池 IIS7 /// https://forums.iis.net/t/1151611.aspx <returns></returns> static List<ApplicationPool> GetAppPools() { ServerManager().ApplicationPools.ToList(); } bool DoAppPool(; ServerManager iisManager = ServerManager(); ApplicationPool appPool = iisManager.ApplicationPools[appPoolName]; if (appPool != ) { { switch (method.ToLower()) { case stop: appPool.Stop(); ; start: appPool.Start(); recycle: appPool.Recycle(); default: ; } iisManager.CommitChanges(); result = (Exception) { result = https://wenku.baidu.com/view/6fc31eaad1f34693daef3e28.html <param name="username"></param> <param name="pwd"></param> bool CreateAppPool(string username,1)"> pwd) { ServerManager iisManager = iisManager.ApplicationPools.Add(appPoolName); appPool.AutoStart = ; appPool.ManagedPipelineMode = ManagedPipelineMode.Integrated; appPool.ManagedRuntimeVersion = v2.0; appPool.ProcessModel.IdentityType = ProcessModelIdentityType.SpecificUser; appPool.ProcessModel.UserName = username; appPool.ProcessModel.Password = pwd; iisManager.CommitChanges(); 编辑应用程序池 <param name="application"></param> bool EditAppPool(ApplicationPool application) { string appPoolName = application.Name; ServerManager iisManager = ) { appPool.ManagedRuntimeVersion = application.ManagedRuntimeVersion; appPool.ManagedPipelineMode = application.ManagedPipelineMode; iisManager.CommitChanges(); } ; } </returns> bool DeleteAppPool( appPoolName) { ServerManager iisManager = ) { iisManager.ApplicationPools.Remove(appPool); iisManager.CommitChanges(); } 判断某一个站点是否存在 <param name="webSiteName"></param> bool IsExistWebSite( webSiteName) { ServerManager iisManager = ServerManager(); Site site = iisManager.Sites[webSiteName]; return site != 创建某一个站点 <param name="schema"></param> <param name="port"></param> <param name="certHashString"></param> <param name="physicalPath"></param> void CreateWebSite(string webSiteName,1)">string schema,1)">int port,1)">string certHashString,1)"> physicalPath) { ServerManager iisManager = ServerManager(); Site site = string.Compare(schema,1)">http) { site = iisManager.Sites.Add(webSiteName,schema,1)">*:{0}:else httpsbyte[] certHashs = certHashString.HashStringToByteArray(); site = iisManager.Sites.Add(webSiteName,physicalPath,certHashs); enable require SSL Configuration config = iisManager.GetApplicationHostConfiguration(); ConfigurationSection accessSection = config.GetSection(system.webServer/security/accesssslFlags"] = @"Sslthrow new Exception();ToDo….; } site.ServerAutoStart = ; site.Applications[/"].ApplicationPoolName = appPoolName; iisManager.CommitChanges(); } 删除某一个站点 <param name="webSiteName"></param> void DeleteWebSite( iisManager.Sites[webSiteName]; iisManager.Sites.Remove(site); iisManager.CommitChanges(); } #endregion } ? 方案四的代码如下,也是已拖老师的源码,自己做了帮助类封装特定的需求: a-老师的底层类: 数据缓存总线(主要用在Web项目) </summary> [System.Diagnostics.DebuggerStepThrough] partial DataCacheBus { 判断文件是否存在 <param name="filePath"></param> bool IsExistFilePath( filePath) { .IsNullOrWhiteSpace(filePath)) File.Exists(filePath); } GenerateFile 将字符串写成文件 </summary> void GenerateFile(string filePath,1)"> fileContent) { string directoryPath = Path.GetDirectoryName(filePath); Directory.Exists(directoryPath)) { Directory.CreateDirectory(directoryPath); } using (FileStream fs = FileStream(filePath,FileMode.Create,FileAccess.Write,FileShare.Read)) { using (StreamWriter sw = StreamWriter(fs,Encoding.UTF8)) { sw.Write(fileContent); sw.Flush(); } } } GenerateFile 生成文件 <param name="filePath"></param> IsExistFilePath(filePath)) { GenerateFile(filePath,1)">author:wangyunpeng); } } 插入缓存对象 <param name="key"></param> <param name="value"></param> void Insert(string key,1)">object value) { Insert(key,value,(CacheDependency)); } 插入缓存对象(缓存依赖) <param name="value"></param> <param name="dependencyFile">文件依赖</param> object value,1)"> dependencyFile) { GenerateFile(dependencyFile); Insert(key,1)"> CacheDependency(dependencyFile)); } <param name="dependencies">缓存依赖 value,CacheDependency dependencies) { HttpRuntime.Cache.Insert(key,dependencies); } <param name="onRemoveCallBack">缓存消失之后的处理方法 dependencyFile,CacheItemRemovedCallback onRemoveCallBack) { GenerateFile(dependencyFile); HttpRuntime.Cache.Insert(key,1)"> CacheDependency(dependencyFile),Cache.NoAbsoluteExpiration,Cache.NoSlidingExpiration,CacheItemPriority.High,onRemoveCallBack); } 插入缓存对象(绝对过期时间) <param name="absoluteExpiration">绝对过期时间 dependencyFile) { GenerateFile(dependencyFile); HttpRuntime.Cache.Insert(key,absoluteExpiration.ToUniversalTime(),Cache.NoSlidingExpiration); } 插入缓存对象(绝对过期时间,缓存依赖) 插入缓存对象(相对过期时间) <param name="slidingExpiration">相对过期时间 插入缓存对象(相对过期时间,TimeSpan slidingExpiration,slidingExpiration); } 插入缓存对象(绝对过期时间,相对过期时间,缓存依赖) <param name="absoluteExpiration"></param> <param name="slidingExpiration"></param> <param name="dependencyFile"></param> <param name="dependencies"></param> <param name="dependencyFile"></param> <param name="onRemoveCallBack"></param> <param name="dependencies"></param> 删除缓存对象 不等于null表示返回删除的缓存对象,等于null表示缓存中没有指定Key的缓存对象object Delete( key) { HttpRuntime.Cache.Remove(key); } 得到缓存对象 未找到该Key时为 nullobject Get( HttpRuntime.Cache.Get(key); } 获取所有缓存信息(不包含已过期的缓存项) static IDictionaryEnumerator GetAll() { HttpRuntime.Cache.GetEnumerator(); } 获取满足查询条件的Key的内容 <param name="keyContent">要查询的key(可以写的不完整)<param name="count">取出满足条件的最大数量string> GetKey(string keyContent = _OLD_bool contains = true,1)">int count = 1000) { .IsNullOrWhiteSpace(keyContent)) { ArgumentException(nameof(keyContent)); } if (count < 1 ArgumentException(nameof(count)); } object @object = string key = ; keyContent = keyContent.ToLower(); List<string> list = new List<(count); IDictionaryEnumerator enumerator = GetAll(); while (enumerator.MoveNext()) { @object = enumerator.Key; if (@object is ) { key = (@object as ).ToLower(); if (contains) { (key.Contains(keyContent)) { list.Add(key); } } { if (!key.Contains(keyContent) && !key.EndsWith(.html)) { list.Add(key); } } if (list.Count == count) { ; } } } list; } 获取满足查询条件的Key的数量 long GetKeyCount(long count = 0L keyContent.ToLower(); IDictionaryEnumerator enumerator = (key.Contains(keyContent)) { System.Threading.Interlocked.Increment(ref count); } } )) { System.Threading.Interlocked.Increment( count); } } } } count; } } b-封装帮助类-巡航导弹-推荐哈: abstract PayBaseCache { 缓存文件依赖项 </summary> protected string DependencyFile { get; set; } public PayBaseCache( dependencyFile) { this.DependencyFile = System.Web.Hosting.HostingEnvironment.MapPath(~/staticfiles/ dependencyFile); DataCacheBus.GenerateFile(this.DependencyFile); } void AddCache<T>(string cacheKey,T t,1)">int cacheHours = 1) where T : { if (DataCacheBus.Get(cacheKey) == ) { DataCacheBus.Insert(cacheKey,t,TimeSpan.FromHours(cacheHours),1)">this.DependencyFile);相对过期时间 } } public T GetCache<T>( cacheKey) { T t = (T)DataCacheBus.Get(cacheKey);相对过期时间 t; } 删除单个缓存 void DeleteCache( cacheKey) { DataCacheBus.Delete(cacheKey); } 删除当前缓存类所有缓存数据 DeleteAllCache() { 这里注意下:如果文件删不了或者缓存没有起到清除效果,有可能是没有文件权限 if (File.Exists(.DependencyFile)) { File.Delete(.DependencyFile); } } } 支付业务缓存 PayBIZCache : PayBaseCache { readonly PayBIZCache instance = PayBIZCache(); public PayBIZCache() : base(payBizCache.html) { } } PayAccountCache : PayBaseCache { readonly PayAccountCache instance = PayAccountCache(); public PayAccountCache() : payAccountCache.html) { } } ? 简单介绍一下封装类:将缓存类的使用做了抽象,每个子类对应一个对应的缓存文件用于清理特定业务的所有缓存,同时支持清理指定缓存。? ? 缓存依赖项的机制推荐研究一下!!! (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |