控制台应用程序服务的MemoryCache实现

问题描述 投票:0回答:1

我正在尝试使用 Microsoft.Extensions.Caching.Memory 命名空间将应用程序缓存添加到 Net 8 控制台应用程序。我已经完成了一半,但已经达到了一个地步,当缓存运行时,我不知道如何管理缓存,其中包含 1,000 多个项目。在我的 GenericHostBuilder 类中,我设置了以下缓存选项:

  private static void BuildMemoryCacheOptions(MemoryCacheOptions _MemoryCacheOptions)
  {
    _MemoryCacheOptions = new MemoryCacheOptions();
    _MemoryCacheOptions.Clock = new Microsoft.Extensions.Internal.SystemClock();
    _MemoryCacheOptions.SizeLimit = 1024 * 1024;
    _MemoryCacheOptions.TrackLinkedCacheEntries = false;
    _MemoryCacheOptions.ExpirationScanFrequency = new TimeSpan(0, 2, 0);
    _MemoryCacheOptions.CompactionPercentage = 0.15;
    _MemoryCacheOptions.TrackStatistics = true;
  }

GenericHostBuilder 将其实现为服务。

_HostApplicationBuilder.Services.AddMemoryCache(BuildMemoryCacheOptions);

然后,我在构造函数调用期间将其作为全局作用域变量添加到我的类中,并作为作用域服务提供者上的单例:

private _MemoryCache = _ServiceProvider.GetRequiredService<MemoryCache>();

然后我可以在方法中使用它来将缓存项目添加到应用程序缓存,并将往返保存到数据库,如下所示:

 public Domain? AddAnyLengthName(ref TopLevelDomain _TLD, string _DomainName, bool _IsValidName)
 {
    Domain? _Domain = _Domain = null;
    MyDBContext _DbContext = _ServiceProvider.GetRequiredService<MyDBContext>();
    string _RootDomainName = DomainDTO.ConvertToRootDomainName(_DomainName);
    _Domain = new Domain(_RootDomainName, _TLD);
    _Domain.IsValidDomainName = _IsValidName;
    _DbContext.Domains.Add(_Domain);
    _DbContext.SaveChanges();

    Domain _CachedDomain = _MemoryCache.Set(_Domain.DomainName, _Domain);
    ICacheEntry _CacheEntry = _MemoryCache.CreateEntry(_CachedDomain);
    _CacheEntry.SlidingExpiration = new TimeSpan(0, 3, 0);
    return _Domain;
  }

所有这些都非常有效,并且性能提升非常显着。但是,最终缓存会被填满,性能开始受到影响。当 MemoryCache 组件从服务容器中出来时,它的类型已更改为 IMemoryCache 类型,这就是我遇到问题的地方,因为此接口默认情况下包含在 MemoryCache 类中的几个缺少的属性和方法,并且我'尚未找到解决此问题的解决方案。

IMemoryCache 有一个方法 GetCurrentStatistics() 和一个属性 Count。 Count 返回缓存中的项目数,但当我尝试使用 GetCurrentStatistics() 时,它始终为 null,并且没有其他属性或方法允许我迭代缓存中的项目。 所以,目前我还没有办法管理缓存内容。

另一方面,如果不将 MemoryCache 实现为服务,而是直接在类中实现它,然后将其作为参数传递,我就可以访问这些额外的方法和属性,让我管理缓存内容,例如作为 Clear() 来清除缓存中的所有项目,或允许我迭代缓存内容的枚举器,而无需提前知道缓存项目的每个键是什么。

我的问题是:

  1. 我是否需要在项目中包含其他包才能从 IMemoryCache 实例访问这些属性和方法?
  2. 我是否缺少 MemoryCacheOption?
  3. 还有其他方法可以实现吗?仍然作为服务,但具有一些附加属性和方法,也许包装在自定义类中?
  4. 还有什么我没有考虑到的吗?

我什至尝试将 MemoryCache 添加到我的 DbContextOptions 中,如下所示:

_DbContextOptionsBuilder.UseMemoryCache(new MemoryCache(GetMemoryCacheOptions()));

但是当我去检索它时,我无法使用 ServiceProvider.GetRequiredService() 来获取它,所以也许还有另一种方法可以做到这一点,但我还没有看到任何文档。

这是我第一次使用这个组件,所以我确信还有其他方法可以达到我想要的效果,我只是还没有找到与 ASP 以外的任何内容相关的 MS 网页或博客。 NET 实现,这是一个控制台应用程序,没有 Web 部件。

预先感谢您的想法和建议。

caching memory microservices
1个回答
0
投票

在花了几天时间尝试解决该组件的 MS Learn 文档与您在实际位和运行时行为中看到的内容之间的脱节之后,我通读了处理该组件的团队成员之间交换的对话。

据我所知,问题不在 MemroyCache 的基本代码中,而是更深入,深入到 Net Framework 本身,我正在运行 Net8。不幸的是,没有给出关于该主题的具体细节,使得 MemoryCache 在某种程度上成为一个黑匣子。在问题严重的地方,我们决定封锁一些属性和方法,使它们不可用或返回 null 或零。

我确信有比我更聪明的开发人员,他们可以解决这些问题并仍然使其适用于他们的特定情况,但这需要我无法承诺的时间和精力。

我的选择是:

  1. 从 Github 下载 MemoryCache 代码并开发我自己的解决方案。
  2. 转到 NuGet 并使用其他开发人员发布的包。

我选择了选项2

尽管如此,对于像宣传的那样工作的 MemoryCache 部分,我的应用程序的性能改进是巨大的,将处理时间从几分钟缩短到几秒钟。因此,对于任何处理大量数据和长处理时间的应用程序来说,MemoryCache 的核心目标仍然是坚实且具有挑战性的。希望 MS 能够尽快解决核心问题。

© www.soinside.com 2019 - 2024. All rights reserved.