提交代码
This commit is contained in:
parent
898153e42f
commit
efd6db3458
|
|
@ -0,0 +1,44 @@
|
|||
using CloudGaming.Code.Config;
|
||||
using CloudGaming.ExtApi.Base;
|
||||
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
using System.Text;
|
||||
|
||||
namespace CloudGaming.ExtApi.Controllers
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// 缓存管理
|
||||
/// </summary>
|
||||
public class CacheController : CloudGamingControllerBase
|
||||
{
|
||||
public CacheController(IServiceProvider _serviceProvider) : base(_serviceProvider)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清除缓存
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpGet]
|
||||
public async Task<IActionResult> ClearAllCacheData()
|
||||
{
|
||||
var outputStream = Response.Body;
|
||||
|
||||
Response.ContentType = "text/plain"; // 设置响应内容类型
|
||||
Response.StatusCode = 200; // 设置状态码
|
||||
await foreach (var item in new AppConfigBLL(ServiceProvider).ClearAllCacheData())
|
||||
{
|
||||
if (item == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
await outputStream.WriteAsync(Encoding.UTF8.GetBytes(item));
|
||||
await outputStream.FlushAsync();
|
||||
}
|
||||
return new EmptyResult();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -49,4 +49,5 @@ public class MonitorController : CloudGamingControllerBase
|
|||
return await new MonitorBLL(ServiceProvider).GetAppMonitorHourAsync(startTimeStamp, endTimeStamp);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,14 @@
|
|||
using CloudGaming.AppConfigModel;
|
||||
using CloudGaming.Code.AppExtend;
|
||||
using CloudGaming.Code.DataAccess.MultiTenantUtil;
|
||||
using CloudGaming.Code.Extend;
|
||||
using CloudGaming.Code.Filter;
|
||||
using CloudGaming.Code.Game;
|
||||
using CloudGaming.Code.Monitor;
|
||||
using CloudGaming.DtoModel;
|
||||
using CloudGaming.GameModel.Db.Db_Ext;
|
||||
using CloudGaming.GameModel.Db.Db_Game;
|
||||
using CloudGaming.Model.DbSqlServer.Db_User;
|
||||
|
||||
using HuanMeng.DotNetCore.CustomExtension;
|
||||
using HuanMeng.DotNetCore.MiddlewareExtend;
|
||||
|
|
@ -44,16 +48,10 @@ builder.Services.AddSingleton(typeof(ILogger<ExceptionMiddleware>), serviceProvi
|
|||
#endregion
|
||||
#region automap
|
||||
var mapperDomain = AppDomain.CurrentDomain.GetAssemblies().Where(it => it.FullName.Contains("HuanMeng") || it.FullName.Contains("CloudGaming.")).ToList();
|
||||
Type type = typeof(T_App_Config);
|
||||
if (type != null)
|
||||
{
|
||||
Assembly assembly = Assembly.GetAssembly(type);
|
||||
if (!mapperDomain.Any(it => it.FullName == assembly.FullName))
|
||||
{
|
||||
mapperDomain.Add(assembly);
|
||||
}
|
||||
}
|
||||
|
||||
AddAssembly(mapperDomain, typeof(T_App_Config));
|
||||
AddAssembly(mapperDomain,typeof(AppConfig));
|
||||
AddAssembly(mapperDomain, typeof(AppConfigCache));
|
||||
AddAssembly(mapperDomain, typeof(T_User));
|
||||
builder.Services.AddAutoMapper(mapperDomain);
|
||||
#endregion
|
||||
#region 添加跨域
|
||||
|
|
@ -140,3 +138,16 @@ app.UseAppRequest("ext");
|
|||
#endregion
|
||||
#endregion
|
||||
app.Run();
|
||||
|
||||
void AddAssembly(List<Assembly> mapperDomain, Type type)
|
||||
{
|
||||
|
||||
if (type != null)
|
||||
{
|
||||
Assembly assembly = Assembly.GetAssembly(type);
|
||||
if (!mapperDomain.Any(it => it.FullName == assembly.FullName))
|
||||
{
|
||||
mapperDomain.Add(assembly);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -246,6 +246,7 @@ namespace CloudGaming.Code.AppExtend
|
|||
newAppConfig.PrivacyAgreement = appConfig.PrivacyAgreement;
|
||||
newAppConfig.UserAgreement = appConfig.UserAgreement;
|
||||
newAppConfig.LanguageRequestUrl = appConfig.LanguageRequestUrl;
|
||||
newAppConfig.CacheRequestUrls = appConfig.CacheRequestUrls;
|
||||
return newAppConfig;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -25,13 +25,13 @@ namespace CloudGaming.Code.Cache.Special
|
|||
/// <param name="database"></param>
|
||||
/// <param name="mapper"></param>
|
||||
/// <param name="appConfig"></param>
|
||||
public class AppConfigEntityCache(DAO dao, IDatabase database, IMapper mapper, AppConfig appConfig) : RedisDataEntityCache<AppConfigCache>(database, 0)
|
||||
public class AppConfigEntityCache(DAO dao, IDatabase database, IMapper mapper, AppConfig appConfig) : RedisDataEntityCache<AppConfigCache>(database, 0, "系统配置")
|
||||
{
|
||||
public override string key => $"cache:appconfig:list";
|
||||
|
||||
public override List<AppConfigCache> GetDataList()
|
||||
{
|
||||
var list = dao.DaoExt.Context.T_App_Config.Where(it => it.ConfigType !=(int)AppConfigType.协议配置).ToList();
|
||||
var list = dao.DaoExt.Context.T_App_Config.Where(it => it.ConfigType != (int)AppConfigType.协议配置).ToList();
|
||||
var appList = mapper.Map<List<AppConfigCache>>(list);
|
||||
return appList;
|
||||
|
||||
|
|
|
|||
|
|
@ -120,7 +120,7 @@ namespace CloudGaming.Code.Cache.Special
|
|||
.Select(entry => JsonConvert.DeserializeObject<GameInfo>(entry.Value))
|
||||
.ToList();
|
||||
|
||||
MemoryCacheHelper.SetCache(key, list, 10);
|
||||
MemoryCacheHelper.SetCache(key, list, 60 * 60 * 12);
|
||||
_dataList = list;
|
||||
return _dataList;
|
||||
}
|
||||
|
|
@ -135,8 +135,8 @@ namespace CloudGaming.Code.Cache.Special
|
|||
.Select(info => new HashEntry($"gameInfo:{info.GameId}", JsonConvert.SerializeObject(info)))
|
||||
.ToArray();
|
||||
database.HashSet(RedisKey, serializedGameInfos);
|
||||
|
||||
MemoryCacheHelper.SetCache(key, tempDataList, 60 * 60);
|
||||
database.StringSet($"time:{RedisKey.Replace(":", ".")}", $"刷新游戏缓存时间{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}");
|
||||
MemoryCacheHelper.SetCache(key, tempDataList, 60 * 60 * 12);
|
||||
_dataList = tempDataList;
|
||||
database.KeyDelete(locaKey);
|
||||
return _dataList;
|
||||
|
|
@ -216,26 +216,20 @@ namespace CloudGaming.Code.Cache.Special
|
|||
|
||||
public override bool ClearData()
|
||||
{
|
||||
lock (GameEntityCacheLock)
|
||||
{
|
||||
database.KeyDelete(RedisKey);
|
||||
MemoryCacheHelper.DelCache(key);
|
||||
_dataList = null;
|
||||
gameInfoDic = null;
|
||||
}
|
||||
database.KeyDelete(RedisKey);
|
||||
MemoryCacheHelper.DelCache(key);
|
||||
_dataList = null;
|
||||
gameInfoDic = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void ReloadData()
|
||||
{
|
||||
lock (lockObj)
|
||||
{
|
||||
database.KeyDelete(RedisKey);
|
||||
MemoryCacheHelper.DelCache(key);
|
||||
_dataList = null;
|
||||
gameInfoDic = null;
|
||||
var x = DataList;
|
||||
}
|
||||
database.KeyDelete(RedisKey);
|
||||
MemoryCacheHelper.DelCache(key);
|
||||
_dataList = null;
|
||||
gameInfoDic = null;
|
||||
var x = DataList;
|
||||
}
|
||||
|
||||
public bool ClearLocalData()
|
||||
|
|
|
|||
|
|
@ -199,12 +199,86 @@ public class ImageEntityCache : ICacheClearData, ICacheReloadData, ICacheClearLo
|
|||
database.StringSet($"{redisKey}:language:{_language}", d);
|
||||
}
|
||||
database.StringSet($"{redisKey}:language", languages);
|
||||
|
||||
database.StringSet($"time:{redisKey.Replace(":", ".")}", $"刷新图片缓存时间{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}");
|
||||
#endregion
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
public void LoadRedisDatabase()
|
||||
{
|
||||
|
||||
var data = new ConcurrentDictionary<string, ConcurrentDictionary<int, string>>();
|
||||
var images = dao.DaoExt.Context.T_App_Image
|
||||
.Where(it => !string.IsNullOrEmpty(it.Url))
|
||||
.AsNoTracking()
|
||||
.Select(it => new { it.ImageId, it.Language, it.Url })
|
||||
.ToList();
|
||||
// 设置默认语言
|
||||
if (string.IsNullOrEmpty(appConfig.DefaultLanguage))
|
||||
{
|
||||
appConfig.DefaultLanguage = "zh";
|
||||
}
|
||||
// 创建默认语言的图像字典
|
||||
var defaultImage = images
|
||||
.Where(it => it.Language == appConfig.DefaultLanguage)
|
||||
.GroupBy(it => it.ImageId)
|
||||
.ToDictionary(group => group.Key, group => appConfig.AliyunConfig.ImagePrefix + group.Last().Url);
|
||||
if (defaultImage == null)
|
||||
{
|
||||
defaultImage = new Dictionary<int, string>();
|
||||
}
|
||||
foreach (var image in images)
|
||||
{
|
||||
if (string.IsNullOrEmpty(image.Url))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
var languageCache = data.GetOrAdd(image.Language, _ => new ConcurrentDictionary<int, string>());
|
||||
var url = string.Empty;
|
||||
if (image.Url.StartsWith("http://") || image.Url.StartsWith("https://"))
|
||||
{
|
||||
url = $"{image.Url}";
|
||||
}
|
||||
else
|
||||
{
|
||||
url = $"{appConfig.AliyunConfig.ImagePrefix}{image.Url}";
|
||||
}
|
||||
languageCache[image.ImageId] = url;
|
||||
// 如果默认图像字典中没有此ImageId,加入默认图像字典
|
||||
if (!defaultImage.ContainsKey(image.ImageId))
|
||||
{
|
||||
defaultImage[image.ImageId] = url;
|
||||
}
|
||||
}
|
||||
#region 保存默认图片
|
||||
var defaultLanguageCache = new ConcurrentDictionary<int, string>(defaultImage);
|
||||
foreach (var kv in defaultLanguageCache)
|
||||
{
|
||||
database.StringSet($"{redisKey}:default:{kv.Key}", kv.Value);
|
||||
}
|
||||
//data.TryAdd("default", defaultLanguageCache);
|
||||
#endregion
|
||||
#region 保存其他图片
|
||||
foreach (var _language in languages)
|
||||
{
|
||||
var mKey = $"{appConfig.Identifier}:App:Image:{_language}";
|
||||
if (!data.TryGetValue(_language, out var d))
|
||||
{
|
||||
d = defaultLanguageCache;
|
||||
}
|
||||
foreach (var kv in d)
|
||||
{
|
||||
database.StringSet($"{redisKey}:{_language}:{kv.Key}", kv.Value);
|
||||
}
|
||||
database.StringSet($"{redisKey}:language:{_language}", d);
|
||||
}
|
||||
database.StringSet($"{redisKey}:language", languages);
|
||||
database.StringSet($"time:{redisKey.Replace(":", ".")}", $"刷新图片缓存时间{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}");
|
||||
#endregion
|
||||
return;
|
||||
}
|
||||
|
||||
public bool ClearData()
|
||||
{
|
||||
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ namespace CloudGaming.Code.Cache.Special;
|
|||
/// <param name="database"></param>
|
||||
/// <param name="mapper"></param>
|
||||
/// <param name="appConfig"></param>
|
||||
public class ProductCacheEntityCache(DAO dao, IDatabase database, IMapper mapper) : RedisDataEntityCache<ProductCache>(database, 60 * 60 * 12)
|
||||
public class ProductCacheEntityCache(DAO dao, IDatabase database, IMapper mapper) : RedisDataEntityCache<ProductCache>(database, 60 * 60 * 12,"产品")
|
||||
{
|
||||
public override string key => "cache:Product:list";
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ namespace CloudGaming.Code.Cache.Special;
|
|||
/// <param name="dao"></param>
|
||||
/// <param name="database"></param>
|
||||
/// <param name="mapper"></param>
|
||||
public class RedemptionCodeEntityCache(DAO dao, IDatabase database, IMapper mapper) : RedisDataEntityCache<RedemptionCodeCache>(database,60 * 60 * 1)
|
||||
public class RedemptionCodeEntityCache(DAO dao, IDatabase database, IMapper mapper) : RedisDataEntityCache<RedemptionCodeCache>(database,60 * 60 * 1, "兑换码")
|
||||
{
|
||||
public override List<RedemptionCodeCache> GetDataList()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ namespace CloudGaming.Code.Cache.Special;
|
|||
/// <param name="dao"></param>
|
||||
/// <param name="database"></param>
|
||||
/// <param name="mapper"></param>
|
||||
public class SevenDayEntityCache(DAO dao, IDatabase database, IMapper mapper) : RedisDataEntityCache<SevenDayCache>(database, 60 * 60 * 24 * 7)
|
||||
public class SevenDayEntityCache(DAO dao, IDatabase database, IMapper mapper) : RedisDataEntityCache<SevenDayCache>(database, 60 * 60 * 24 * 7, "七天签到")
|
||||
{
|
||||
public override List<SevenDayCache> GetDataList()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,12 +1,20 @@
|
|||
using Azure;
|
||||
|
||||
using CloudGaming.AppConfigModel;
|
||||
using CloudGaming.Code.AppExtend;
|
||||
using CloudGaming.Code.Cache;
|
||||
using CloudGaming.DtoModel;
|
||||
|
||||
using StackExchange.Redis;
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using static SKIT.FlurlHttpClient.Wechat.TenpayV3.Models.CreateNewTaxControlFapiaoApplicationRequest.Types.Fapiao.Types;
|
||||
|
||||
namespace CloudGaming.Code.Config
|
||||
{
|
||||
/// <summary>
|
||||
|
|
@ -68,5 +76,86 @@ namespace CloudGaming.Code.Config
|
|||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清除缓存
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
/// <summary>
|
||||
/// 清除缓存
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async IAsyncEnumerable<string> ClearAllCacheData()
|
||||
{
|
||||
// 开始总耗时计时
|
||||
var swAll = Stopwatch.StartNew();
|
||||
|
||||
// 删除应用配置缓存
|
||||
var delAppConfig = Stopwatch.StartNew();
|
||||
var keysDeleted = (int)await RedisCache.KeysDeleteds("App:Config:*");
|
||||
delAppConfig.Stop();
|
||||
yield return $"删除app配置:{keysDeleted}, 耗时==》{delAppConfig.ElapsedMilliseconds.ToString("0.##")}毫秒";
|
||||
|
||||
// 删除API接口缓存
|
||||
var apiCache = Stopwatch.StartNew();
|
||||
var keysDeleted1 = (int)await RedisCache.KeysDeleteds("cache:api:*");
|
||||
apiCache.Stop();
|
||||
yield return $"删除api接口缓存:{keysDeleted1}, 耗时==》{apiCache.ElapsedMilliseconds.ToString("0.##")}毫秒";
|
||||
|
||||
// 删除图片缓存
|
||||
var imageCache = Stopwatch.StartNew();
|
||||
var imageDel = (int)await RedisCache.KeysDeleteds("cache:Image:*");
|
||||
imageCache.Stop();
|
||||
yield return $"删除图片缓存:{imageDel}, 耗时==》{imageCache.ElapsedMilliseconds.ToString("0.##")}毫秒";
|
||||
|
||||
// 重新加载缓存
|
||||
var reloadCache = Stopwatch.StartNew();
|
||||
Cache.AppImageCache.LoadRedisDatabase();
|
||||
yield return $"重新加载图片缓存";
|
||||
Cache.GameEntityCache.ReloadData();
|
||||
yield return $"重新加载游戏缓存";
|
||||
Cache.AppConfigCache.ReloadData();
|
||||
yield return $"重新加载系统配置缓存";
|
||||
Cache.ProductCacheEntityCache.ReloadData();
|
||||
yield return $"重新加载产品缓存";
|
||||
Cache.RedemptionCodeEntityCache.ReloadData();
|
||||
yield return $"重新加载兑换码缓存";
|
||||
Cache.SevenDayEntityCache.ReloadData();
|
||||
yield return $"重新加载七天签到缓存";
|
||||
reloadCache.Stop();
|
||||
yield return $"全部重新加载缓存耗时==》{reloadCache.ElapsedMilliseconds.ToString("0.##")}毫秒";
|
||||
|
||||
// 清除本地缓存
|
||||
var clearLocalCache = Stopwatch.StartNew();
|
||||
ClearCacheData();
|
||||
clearLocalCache.Stop();
|
||||
yield return $"清除本地缓存, 耗时==》{clearLocalCache.ElapsedMilliseconds.ToString("0.##")}毫秒";
|
||||
|
||||
// 清除网络缓存
|
||||
var clearNetworkCache = Stopwatch.StartNew();
|
||||
var urls = AppConfig.CacheRequestUrls ?? new List<string>();
|
||||
foreach (var url in urls)
|
||||
{
|
||||
string resp = string.Empty;
|
||||
try
|
||||
{
|
||||
var client = HttpClientFactory.CreateClient();
|
||||
var data = await client.GetAsync(url);
|
||||
resp = $"清除网络缓存{url}===》{data}";
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
resp = $"清除网络缓存{url}失败===》{ex.Message}";
|
||||
}
|
||||
yield return resp;
|
||||
}
|
||||
clearNetworkCache.Stop();
|
||||
yield return $"清除网络缓存耗时==》{clearNetworkCache.ElapsedMilliseconds.ToString("0.##")}毫秒";
|
||||
|
||||
// 停止总耗时计时
|
||||
swAll.Stop();
|
||||
yield return $"清除结束, 总耗时==》{swAll.ElapsedMilliseconds.ToString("0.##")}毫秒";
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -89,6 +89,11 @@ namespace CloudGaming.AppConfigModel
|
|||
/// 多语言列表请求地址
|
||||
/// </summary>
|
||||
public string LanguageRequestUrl { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 清除缓存接口
|
||||
/// </summary>
|
||||
public List<string> CacheRequestUrls { get; set; }
|
||||
/// <summary>
|
||||
/// 获取数据库连接字符串
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -117,11 +117,14 @@ public abstract class RedisDataEntityCache<T> : CommonDataEntityCache<T>, ICache
|
|||
/// </summary>
|
||||
protected int cacheTime;
|
||||
|
||||
protected RedisDataEntityCache(IDatabase database,int cacheTime = 36000) : base(new object(), cacheTime)
|
||||
private string name;
|
||||
|
||||
protected RedisDataEntityCache(IDatabase database, int cacheTime = 36000, string name = "") : base(new object(), cacheTime)
|
||||
{
|
||||
this.lockObj = lockObj;
|
||||
this.cacheTime = cacheTime;
|
||||
this.database = database;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public int index = 0;
|
||||
|
|
@ -212,6 +215,8 @@ public abstract class RedisDataEntityCache<T> : CommonDataEntityCache<T>, ICache
|
|||
}
|
||||
_dataList = tempDataList;
|
||||
database.KeyDeleteAsync($"lock:{key}").Wait();
|
||||
database.StringSet($"time:{key.Replace(":", ".")}", $"刷新{name}缓存时间{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -132,6 +132,29 @@ namespace HuanMeng.DotNetCore.Redis
|
|||
return database.StringSet(key, value, TimeSpan.FromSeconds(time), when: When.NotExists);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除key
|
||||
/// </summary>
|
||||
/// <param name="database"></param>
|
||||
/// <param name="key"></param>
|
||||
/// <returns></returns>
|
||||
public static async Task<int> KeysDeleteds(this IDatabase database, string key)
|
||||
{
|
||||
|
||||
string luaScript = @"
|
||||
local keys = redis.call('KEYS', ARGV[1])
|
||||
if next(keys) ~= nil then
|
||||
return redis.call('DEL', unpack(keys))
|
||||
else
|
||||
return 0
|
||||
end
|
||||
";
|
||||
|
||||
var keysDeleted = (int)await (database.ScriptEvaluateAsync(luaScript, values: new RedisValue[] { key }));
|
||||
return keysDeleted;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 获取一个key的对象
|
||||
/// </summary>
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user