net core web 项目最高效、最规范的主动内存缓存实现
很多人会直接用静态类做内存缓存,包括我自己之前也是这样做,但这样内存的生命周期及GC机制得不到保障,特别是对于多线程的控制,静态类都是无能为力。
另外就是 MemoryCache,很多人都习惯用他的 MemoryCache.TryGetValue 来实现自动缓存,这对于小项目及访问量不大的项目是可行的,但如果对于大项目,这样会导致访问很慢,因为是被动式的去拉取数据,有没有一种更好的方式呢,好在net core 提供了 BackgroundService 及 IHostedService,两者类似,可以完美的解决我们的需求,这里我就举例说一下使用 IHostedService 来实现主动式缓存网站首页的全部数据,以实现最快速的首页访问。
新建逻辑处理服务类:
public class DbServices : IHostedService, IDisposable
{
CancellationToken cancelToken;
HomeData? datas;
Task? mainTask;
private ILogger logger;
public DbServices(ILogger logger)
{
this.logger=logger;
}
public HomeData? GetHomeData()
{
return datas;
}
public Task StartAsync(CancellationToken cancellationToken)
{
cancelToken = cancellationToken;
mainTask = Task.Factory.StartNew(HomeDataWork, cancellationToken);
return Task.CompletedTask;
}
private async void HomeDataWork()
{
DateTime last = DateTime.Now.AddMinutes(-2);
while (!cancelToken.IsCancellationRequested)
{
int sec = 30000 - (int)(DateTime.Now - last).TotalMilliseconds;
if (sec > 0)
await Task.Delay(sec);
last = DateTime.Now;
HomeData? _data = .....;//实现获取数据
}
}
public Task StopAsync(CancellationToken cancellationToken)
{
return Task.CompletedTask;
}
public void Dispose()
{
mainTask?.Dispose();
}
}
Program.cs 中:
builder.Services.AddSingleton<DbServices>();
builder.Services.AddHostedService<DbServices>(provider => provider.GetService<DbServices>());
大功造成,该服务会在后台主动更新内存数据,首页可以直接无任何延迟直接获取数据:
DbServices? service = MyHttpContext.Current?.RequestServices.GetService(typeof(DbServices)) as DbServices;
HomeData = service?.GetHomeData(Langs.Instance.LangCode) ?? new();