feat: 优化访问数量统计,采用本地缓存+分布式缓存+数据库
This commit is contained in:
@@ -4,7 +4,9 @@ using Microsoft.Extensions.Configuration;
|
|||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
using Volo.Abp.Caching;
|
using Volo.Abp.Caching;
|
||||||
using Volo.Abp.DependencyInjection;
|
using Volo.Abp.DependencyInjection;
|
||||||
|
using Volo.Abp.EventBus;
|
||||||
using Yi.Framework.Bbs.Domain.Shared.Caches;
|
using Yi.Framework.Bbs.Domain.Shared.Caches;
|
||||||
|
using Yi.Framework.Bbs.Domain.Shared.Etos;
|
||||||
|
|
||||||
namespace Yi.Framework.Bbs.Application.Extensions;
|
namespace Yi.Framework.Bbs.Application.Extensions;
|
||||||
|
|
||||||
@@ -14,6 +16,29 @@ namespace Yi.Framework.Bbs.Application.Extensions;
|
|||||||
/// 需考虑一致性问题,又不能上锁影响性能
|
/// 需考虑一致性问题,又不能上锁影响性能
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class AccessLogMiddleware : IMiddleware, ITransientDependency
|
public class AccessLogMiddleware : IMiddleware, ITransientDependency
|
||||||
|
{
|
||||||
|
private static int _accessLogNumber = 0;
|
||||||
|
|
||||||
|
internal static void ResetAccessLogNumber()
|
||||||
|
{
|
||||||
|
_accessLogNumber = 0;
|
||||||
|
}
|
||||||
|
internal static int GetAccessLogNumber()
|
||||||
|
{
|
||||||
|
return _accessLogNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public async Task InvokeAsync(HttpContext context, RequestDelegate next)
|
||||||
|
{
|
||||||
|
await next(context);
|
||||||
|
|
||||||
|
Interlocked.Increment(ref _accessLogNumber);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class AccessLogResetEventHandler : ILocalEventHandler<AccessLogResetArgs>,
|
||||||
|
ITransientDependency
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 缓存前缀
|
/// 缓存前缀
|
||||||
@@ -39,13 +64,28 @@ public class AccessLogMiddleware : IMiddleware, ITransientDependency
|
|||||||
return redisEnabled.IsNullOrEmpty() || bool.Parse(redisEnabled);
|
return redisEnabled.IsNullOrEmpty() || bool.Parse(redisEnabled);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task InvokeAsync(HttpContext context, RequestDelegate next)
|
//该事件由job定时10秒触发
|
||||||
|
public async Task HandleEventAsync(AccessLogResetArgs eventData)
|
||||||
{
|
{
|
||||||
await next(context);
|
|
||||||
if (EnableRedisCache)
|
if (EnableRedisCache)
|
||||||
{
|
{
|
||||||
await RedisClient.IncrByAsync($"{CacheKeyPrefix}:{AccessLogCacheConst.Key}:{DateTime.Now.Date}", 1);
|
//分布式锁
|
||||||
|
if (await RedisClient.SetNxAsync("AccessLogLock",true,TimeSpan.FromSeconds(5)))
|
||||||
|
{
|
||||||
|
//自增长数
|
||||||
|
var incrNumber= AccessLogMiddleware.GetAccessLogNumber();
|
||||||
|
//立即重置,开始计算,方式丢失
|
||||||
|
AccessLogMiddleware.ResetAccessLogNumber();
|
||||||
|
if (incrNumber>0)
|
||||||
|
{
|
||||||
|
await RedisClient.IncrByAsync(
|
||||||
|
$"{CacheKeyPrefix}:{AccessLogCacheConst.Key}:{DateTime.Now.Date.ToString("yyyyMMdd")}", incrNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
using FreeRedis;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
using Quartz;
|
||||||
|
using Volo.Abp.BackgroundWorkers.Quartz;
|
||||||
|
using Volo.Abp.Caching;
|
||||||
|
using Volo.Abp.DependencyInjection;
|
||||||
|
using Volo.Abp.Domain.Entities;
|
||||||
|
using Volo.Abp.EventBus.Local;
|
||||||
|
using Yi.Framework.Bbs.Domain.Entities;
|
||||||
|
using Yi.Framework.Bbs.Domain.Shared.Caches;
|
||||||
|
using Yi.Framework.Bbs.Domain.Shared.Enums;
|
||||||
|
using Yi.Framework.Bbs.Domain.Shared.Etos;
|
||||||
|
using Yi.Framework.SqlSugarCore.Abstractions;
|
||||||
|
|
||||||
|
namespace Yi.Framework.Bbs.Application.Jobs;
|
||||||
|
|
||||||
|
public class AccessLogCacheJob : QuartzBackgroundWorkerBase
|
||||||
|
{
|
||||||
|
private readonly ILocalEventBus _localEventBus;
|
||||||
|
|
||||||
|
public AccessLogCacheJob(ILocalEventBus localEventBus)
|
||||||
|
{
|
||||||
|
_localEventBus = localEventBus;
|
||||||
|
JobDetail = JobBuilder.Create<AccessLogCacheJob>().WithIdentity(nameof(AccessLogCacheJob))
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
//每10秒执行一次,将本地缓存转入redis,防止丢数据
|
||||||
|
Trigger = TriggerBuilder.Create().WithIdentity(nameof(AccessLogCacheJob))
|
||||||
|
.WithSimpleSchedule((schedule) => { schedule.WithInterval(TimeSpan.FromSeconds(10)).RepeatForever();; })
|
||||||
|
.Build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task Execute(IJobExecutionContext context)
|
||||||
|
{
|
||||||
|
await _localEventBus.PublishAsync(new AccessLogResetArgs());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -81,7 +81,7 @@ public class AccessLogStoreJob : QuartzBackgroundWorkerBase
|
|||||||
}
|
}
|
||||||
|
|
||||||
//删除前一天的缓存
|
//删除前一天的缓存
|
||||||
await RedisClient.DelAsync($"{CacheKeyPrefix}:{AccessLogCacheConst.Key}:{DateTime.Now.Date.AddDays(-1)}");
|
await RedisClient.DelAsync($"{CacheKeyPrefix}:{AccessLogCacheConst.Key}:{DateTime.Now.Date.AddDays(-1).ToString("yyyyMMdd")}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
namespace Yi.Framework.Bbs.Domain.Shared.Etos;
|
||||||
|
|
||||||
|
public class AccessLogResetArgs
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user