internal static int CalcCacheSeconds(ControllerActionDescriptor controllerActionDescriptor, out string cacheTimeSetting) { object[] responseCache; if (controllerActionDescriptor.ControllerTypeInfo.Name.EndsWith("Proxy")) { // 代理类,从源类型中查找相关特性 var sourceControllerType = AppManager.ProxyOriginalTypes[controllerActionDescriptor.ControllerTypeInfo.FullName]; var methodInfo = sourceControllerType.GetMethod(controllerActionDescriptor.MethodInfo.Name); responseCache = methodInfo.GetCustomAttributes(typeof(CacheAttribute), true); } else { responseCache = controllerActionDescriptor.MethodInfo.GetCustomAttributes(typeof(CacheAttribute), true); } if (responseCache.Count() != 1) { cacheTimeSetting = string.Empty; return(0); } var cache = responseCache[0] as CacheAttribute; cacheTimeSetting = cache.CacheProfileName; return(CacheTimeSettings.GetCacheSeconds(cache.CacheProfileName)); }
private static CacheTimeRate WriteCacheByCacheTimeSetting(object resultValue, string cacheKey, double cacheSeconds, string cacheTimeSetting) { CacheTimeRate cacheTimeRate = null; try { if (cacheSeconds <= 0) { return(null); } cacheTimeRate = CacheTimeSettings.GetCacheTimeRate(); if (cacheTimeRate == null || (cacheTimeRate.AppCacheTime == 0 && cacheTimeRate.RedisCacheTime == 0)) { return(null); } // 对不需要封装的接口,无需封装 if (!resultValue.GetType().ToString().StartsWith("Modobay.Api.ResultDto")) { resultValue = ResultBuilder.AsSuccess(resultValue); } // 本地缓存 if (cacheTimeRate.AppCacheTime > 0 || IsStatic(cacheTimeSetting)) { var seconds = cacheTimeRate.AppCacheTime * cacheSeconds; if (seconds < 60) { seconds = 60; } if (seconds > 600) { seconds = 600; } AppCache.Set(cacheKey, resultValue, TimeSpan.FromSeconds(seconds)); //AppCache.Set(cacheKey, resultValue, TimeSpan.FromSeconds(cacheTimeRate.AppCacheTime * cacheSeconds)); } // 分布式缓存 if (cacheTimeRate.RedisCacheTime > 0 && !IsStatic(cacheTimeSetting)) //if (cacheTimeRate.RedisCacheTime > 0 && !RedisCache.KeyExists(cacheKey)) { RedisCache.Set2(cacheKey, resultValue, TimeSpan.FromSeconds(cacheTimeRate.RedisCacheTime * cacheSeconds)); } // 静态模式更新文件? } catch (Exception ex) { Lib.Log.WriteExceptionLog($"WriteCache Exception:{cacheKey} {ex.Message} <br> StackTrace:{ex.StackTrace}"); } return(cacheTimeRate); }
/// <summary> /// 检查是否可以更新缓存,如果可以,设置正在更新的标识 /// </summary> /// <param name="cacheKey"></param> /// <returns></returns> public static bool CheckUpdateAndFlag(string cacheKey, string cacheTimeSetting = "", string cacheKeyPrefix = null) { var updateKey = $"{(cacheKeyPrefix ?? "UpdateCache")}:{cacheKey}"; var updateFlag = Get <object>(updateKey); var isNeedUpdate = false; if (updateFlag == null) { double seconds = CacheTimeSettings.GetUpdateCacheSeconds(cacheTimeSetting); if (seconds > 0) { Set(updateKey, new object(), TimeSpan.FromSeconds(seconds)); isNeedUpdate = true; } } return(isNeedUpdate); }
internal static ResultDto <dynamic> ReadCache(ActionExecutingContext context, IAppContext appContext) { try { if (!IsEnableApiCache(appContext.AppID)) { return(null); } var cacheTimeRate = CacheTimeSettings.GetCacheTimeRate(); if (cacheTimeRate == null || (cacheTimeRate.AppCacheTime == 0 && cacheTimeRate.RedisCacheTime == 0)) { return(null); } var actionDescriptor = context.ActionDescriptor as ControllerActionDescriptor; var cacheSeconds = CalcCacheSeconds(actionDescriptor, out var cacheTimeSetting); if (cacheSeconds <= 0) { return(null); } ResultDto <dynamic> cacheResult = null; var cacheKey = GetApiCacheKey(actionDescriptor, context.HttpContext); try { if (cacheTimeRate.AppCacheTime > 0) { AppCache.TryGetValue <ResultDto <dynamic> >(cacheKey, out cacheResult); } if (cacheResult == null && cacheTimeRate.RedisCacheTime > 0) { cacheResult = RedisCache.Get2 <ResultDto <dynamic> >(cacheKey); if (cacheResult != null && cacheTimeRate.AppCacheTime > 0) { // 恢复本地缓存 var seconds = cacheTimeRate.AppCacheTime * cacheSeconds; if (seconds < 60) { seconds = 60; } if (seconds > 600) { seconds = 300; } AppCache.Set(cacheKey, cacheResult, TimeSpan.FromSeconds(seconds)); //AppCache.Set(cacheKey, cacheResult, TimeSpan.FromSeconds(cacheTimeRate.AppCacheTime * cacheSeconds)); } } // 存在缓存则检查缓存是否需要更新;如果cacheResult为null,则接口调用完成后由WriteCache写入缓存 if (cacheResult != null) { var isNeedUpdate = CheckUpdateAndFlag(cacheKey, cacheTimeSetting); if (isNeedUpdate) { Task.Run(async() => { var newAppContext = AppManager.CopyAppContext(appContext); await Task.Delay(1); var resultValue = InvokeByActionContext(context, newAppContext); if (resultValue != null) { WriteCacheByCacheTimeSetting(resultValue, cacheKey, cacheSeconds, cacheTimeSetting); } }); } } return(cacheResult); } catch (Exception ex) { Lib.Log.WriteExceptionLog($"ReadCache-{cacheKey} Exception:{cacheKey} {ex.Message} <br> StackTrace:{ex.StackTrace}"); return(null); } } catch (Exception exx) { return(null); } }
private static T GetAndCache <T>(Delegate func, string cacheTimeSetting, string flag = "", params object[] input) { var cacheResult = default(T); var cacheKey = GetDataCacheKey <T>(func, flag); var cacheTime = TimeSpan.FromSeconds(CacheTimeSettings.GetCacheSeconds(cacheTimeSetting)); // 从本地缓存返回 AppCache.TryGetValue(cacheKey, out cacheResult); // 从本地文件返回 if (cacheResult == null && IsStatic(cacheTimeSetting)) { var cacheFileName = GetCacheFileName(cacheKey); if (File.Exists(cacheFileName)) { cacheResult = JsonConvert.DeserializeObject <T>(File.ReadAllText(cacheFileName)); AppCache.Set(cacheKey, cacheResult, cacheTime);// 恢复本地缓存 } } // 从redis缓存返回 if (cacheResult == null && !IsStatic(cacheTimeSetting)) { cacheResult = RedisCache.Get <T>(cacheKey); if (cacheResult != null) { AppCache.Set(cacheKey, cacheResult, cacheTime);// 恢复本地缓存 //if (IsStatic(cacheTimeSetting)) //{ // CacheFile(cacheKey, JsonConvert.SerializeObject(cacheResult), typeof(T).FullName); //} } } // 从数据源返回 if (cacheResult == null) { // 如果其他线程已在获取,则等待,超时再重新获取 var isNeedUpdate = CacheManager.CheckUpdateAndFlag(cacheKey, cacheTimeSetting);//, "UpdateCache:Data" if (!isNeedUpdate) { var index = 0; while (cacheResult == null && index < 30) { index += 1; AppCache.TryGetValue <T>(cacheKey, out cacheResult); if (cacheResult == null) { cacheResult = RedisCache.Get <T>(cacheKey); } if (cacheResult == null) { System.Threading.Thread.Sleep(100); } Lib.StopwatchLog.RecordElapsedMilliseconds($"1 {cacheKey}"); } if (cacheResult != null) { return(cacheResult); } } cacheResult = (T)func.DynamicInvoke(input); Set(cacheKey, cacheResult, cacheTime, true, IsStatic(cacheTimeSetting)); return(cacheResult); } if (cacheTimeSetting != CacheTimeSettings.Second && CacheManager.CheckUpdateAndFlag(cacheKey, cacheTimeSetting) == true) { Task.Run(async() => { await Task.Delay(1); cacheResult = (T)func.DynamicInvoke(input); Set(cacheKey, cacheResult, cacheTime, false, IsStatic(cacheTimeSetting)); }); } // 缓存预热,每隔10分钟,先异步更新缓存,并续期,待下次访问时替换为最新缓存 return(cacheResult); }