ASP.NET Core'da bellek içi önbellek
Rick Anderson, John Luo ve Steve Smith tarafından
Önbelleğe Alma, içerik oluşturmak için gereken çalışmayı azaltarak uygulamanın performansını ve ölçeklenebilirliğini önemli ölçüde geliştirebilir. Önbelleğe Alma, seyrek değişen ve oluşturulması pahalı olan verilerle en iyi şekilde çalışır. Önbelleğe Alma, kaynaktan çok daha hızlı döndürülebilecek verilerin bir kopyasını oluşturur. Uygulamalar hiçbir zaman önbelleğe alınmış verilere bağımlı olmayacak şekilde yazılmalı ve test edilmelidir.
ASP.NET Core birkaç farklı önbelleği destekler. En basit önbellek temel alır IMemoryCache. IMemoryCache
, web sunucusunun belleğinde depolanan bir önbelleği temsil eder. Bir sunucu grubunda (birden çok sunucu) çalışan uygulamalar, bellek içi önbelleği kullanırken oturumların yapışkan olmasını sağlamalıdır. Yapışkan oturumlar, bir istemciden gelen isteklerin tümünün aynı sunucuya gitmesini sağlar. Örneğin, Azure Web uygulamaları tüm istekleri aynı sunucuya yönlendirmek için Uygulama İsteği Yönlendirmesi'ni (ARR) kullanır.
Web grubundaki yapışkan olmayan oturumlar, önbellek tutarlılığı sorunlarını önlemek için dağıtılmış bir önbellek gerektirir. Bazı uygulamalarda, dağıtılmış önbellek bellek içi önbellekten daha yüksek ölçeği genişletmeyi destekleyebilir. Dağıtılmış önbellek kullanmak, önbellek belleğini bir dış işleme boşaltır.
Bellek içi önbellek herhangi bir nesneyi depolayabilir. Dağıtılmış önbellek arabirimi ile byte[]
sınırlıdır. Bellek içi ve dağıtılmış önbellek deposu önbellek öğelerini anahtar-değer çiftleri olarak depolar.
Runtime. Önbelleğe Alma/MemoryCache
System.Runtime.Caching/MemoryCache (NuGet paketi) ile kullanılabilir:
- .NET Standard 2.0 veya üzeri.
- .NET Standard 2.0 veya üstünü hedefleyen herhangi bir .NET uygulaması . Örneğin, Core 3.1 veya sonraki bir sürümü ASP.NET.
- .NET Framework 4.5 veya üzeri.
Microsoft.Extensions. Önbelleğe Alma. ASP.NET Core ile daha iyi tümleştirildiğinden bellek/IMemoryCache
(bu makalede açıklanmıştırSystem.Runtime.Caching
/MemoryCache
) önerilir. Örneğin, IMemoryCache
ASP.NET Core bağımlılık ekleme ile yerel olarak çalışır.
kodu ASP.NET 4.x'ten ASP.NET Core'a aktarırken uyumluluk köprüsü olarak kullanın System.Runtime.Caching
/MemoryCache
.
Önbellek yönergeleri
- Kod her zaman verileri getirmek için bir geri dönüş seçeneğine sahip olmalı ve önbelleğe alınmış bir değerin kullanılabilir olmasına bağlı olmamalıdır .
- Önbellekte az miktarda kaynak ve bellek kullanılır. Önbellek büyümesini sınırla:
- Önbelleğe dış giriş eklemeyin. Örneğin, kullanıcı tarafından sağlanan rastgele girişin önbellek anahtarı olarak kullanılması önerilmez çünkü giriş öngörülemeyen miktarda bellek tüketebilir.
- Önbellek büyümesini sınırlamak için süre sonu kullanma.
- Önbellek boyutunu sınırlamak için SetSize, Size ve SizeLimit kullanın. ASP.NET Core çalışma zamanı, bellek baskısına bağlı olarak önbellek boyutunu sınırlamaz. Önbellek boyutunu sınırlamak geliştiriciye bağlı.
IMemoryCache kullanma
Uyarı
Bağımlılık Ekleme'den paylaşılan bir bellek önbelleği kullanmak ve önbellek boyutunu sınırlamak için , Size
veya SizeLimit
çağrısı SetSize
yapmak uygulamanın başarısız olmasına neden olabilir. Önbellekte boyut sınırı ayarlandığında, tüm girdiler eklenirken bir boyut belirtmelidir. Geliştiriciler paylaşılan önbelleği kullananlar üzerinde tam denetime sahip olmadığından bu sorunlara yol açabilir.
Önbelleği sınırlamak için , Size
veya SizeLimit
kullanırkenSetSize
, önbelleğe alma için bir önbellek teklisi oluşturun. Daha fazla bilgi ve örnek için bkz . Önbellek boyutunu sınırlamak için SetSize, Size ve SizeLimit kullanma.
Paylaşılan önbellek, diğer çerçeveler veya kitaplıklar tarafından paylaşılan önbellektir.
Bellek içi önbelleğe alma, Bağımlılık Ekleme kullanılarak bir uygulamadan başvuruda bulunan bir hizmettir. Oluşturucudaki IMemoryCache
örneği isteyin:
public class IndexModel : PageModel
{
private readonly IMemoryCache _memoryCache;
public IndexModel(IMemoryCache memoryCache) =>
_memoryCache = memoryCache;
// ...
Aşağıdaki kod, bir saatin önbellekte olup olmadığını denetlemek için kullanır TryGetValue . Bir zaman önbelleğe alınmazsa yeni bir giriş oluşturulur ve ile Setönbelleğe eklenir:
public void OnGet()
{
CurrentDateTime = DateTime.Now;
if (!_memoryCache.TryGetValue(CacheKeys.Entry, out DateTime cacheValue))
{
cacheValue = CurrentDateTime;
var cacheEntryOptions = new MemoryCacheEntryOptions()
.SetSlidingExpiration(TimeSpan.FromSeconds(3));
_memoryCache.Set(CacheKeys.Entry, cacheValue, cacheEntryOptions);
}
CacheCurrentDateTime = cacheValue;
}
Önceki kodda, önbellek girişi üç saniyelik kayan süre sonu ile yapılandırılır. Önbellek girdisine üç saniyeden fazla erişilmezse önbellekten çıkarılır. Önbellek girdisine her erişildiğinde, önbellekte 3 saniye daha kalır. CacheKeys
sınıfı, indirme örneğinin bir parçasıdır.
Geçerli saat ve önbelleğe alınan süre görüntülenir:
<ul>
<li>Current Time: @Model.CurrentDateTime</li>
<li>Cached Time: @Model.CacheCurrentDateTime</li>
</ul>
Aşağıdaki kod, verileri göreli bir süre için olmadan MemoryCacheEntryOptions
önbelleğe almak için uzantı yöntemini kullanırSet
:
_memoryCache.Set(CacheKeys.Entry, DateTime.Now, TimeSpan.FromDays(1));
Önceki kodda, önbellek girdisi bir günlük göreli süre sonuyla yapılandırılır. Önbellek girdisi, bu zaman aşımı süresi içinde erişilmiş olsa bile bir gün sonra önbellekten çıkarılır.
Aşağıdaki kod, verileri önbelleğe almak için ve GetOrCreateAsync kullanırGetOrCreate.
public void OnGetCacheGetOrCreate()
{
var cachedValue = _memoryCache.GetOrCreate(
CacheKeys.Entry,
cacheEntry =>
{
cacheEntry.SlidingExpiration = TimeSpan.FromSeconds(3);
return DateTime.Now;
});
// ...
}
public async Task OnGetCacheGetOrCreateAsync()
{
var cachedValue = await _memoryCache.GetOrCreateAsync(
CacheKeys.Entry,
cacheEntry =>
{
cacheEntry.SlidingExpiration = TimeSpan.FromSeconds(3);
return Task.FromResult(DateTime.Now);
});
// ...
}
Önbelleğe alınmış zamanı getirmek için aşağıdaki kod çağrıları Get :
var cacheEntry = _memoryCache.Get<DateTime?>(CacheKeys.Entry);
Aşağıdaki kod, mutlak süre sonuyla önbelleğe alınmış bir öğe alır veya oluşturur:
var cachedValue = _memoryCache.GetOrCreate(
CacheKeys.Entry,
cacheEntry =>
{
cacheEntry.AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(20);
return DateTime.Now;
});
Yalnızca kayan süre sonu olan önbelleğe alınmış bir öğe kümesinin süresi hiç dolmama riski altındadır. Önbelleğe alınan öğeye kayan süre sonu aralığı içinde tekrar tekrar erişilirse, öğenin süresi hiçbir zaman dolmaz. Öğenin süresinin dolduğundan emin olmak için kayan süre sonunu mutlak süre sonuyla birleştirin. Mutlak süre sonu, öğenin ne kadar süre önbelleğe alınabileceğine ilişkin bir üst sınır ayarlar ve kayan süre sonu aralığı içinde istenmezse öğenin süresinin daha erken dolmasına izin verir. Kayan süre sonu aralığı veya mutlak süre sonu süresi geçerse, öğe önbellekten çıkarılır.
Aşağıdaki kod hem kayan hem de mutlak süre sonu olan önbelleğe alınmış bir öğe alır veya oluşturur:
var cachedValue = _memoryCache.GetOrCreate(
CacheKeys.CallbackEntry,
cacheEntry =>
{
cacheEntry.SlidingExpiration = TimeSpan.FromSeconds(3);
cacheEntry.AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(20);
return DateTime.Now;
});
Yukarıdaki kod, verilerin mutlak süreden daha uzun süre önbelleğe alınmayacağını garanti eder.
GetOrCreate, GetOrCreateAsyncve Get sınıfındaki CacheExtensions uzantı yöntemleridir. Bu yöntemler, özelliğini genişletir IMemoryCache.
MemoryCacheEntryOptions
Aşağıdaki örnek:
- Önbellek önceliğini olarak CacheItemPriority.NeverRemoveayarlar.
- Girdi önbellekten çıkarıldıktan sonra çağrılan bir PostEvictionDelegate ayarlar. Geri çağırma, öğeyi önbellekten kaldıran koddan farklı bir iş parçacığında çalıştırılır.
public void OnGetCacheRegisterPostEvictionCallback()
{
var memoryCacheEntryOptions = new MemoryCacheEntryOptions()
.SetPriority(CacheItemPriority.NeverRemove)
.RegisterPostEvictionCallback(PostEvictionCallback, _memoryCache);
_memoryCache.Set(CacheKeys.CallbackEntry, DateTime.Now, memoryCacheEntryOptions);
}
private static void PostEvictionCallback(
object cacheKey, object cacheValue, EvictionReason evictionReason, object state)
{
var memoryCache = (IMemoryCache)state;
memoryCache.Set(
CacheKeys.CallbackMessage,
$"Entry {cacheKey} was evicted: {evictionReason}.");
}
Önbellek boyutunu sınırlamak için SetSize, Size ve SizeLimit kullanma
Bir MemoryCache
örnek isteğe bağlı olarak bir boyut sınırı belirtebilir ve zorunlu kılabilir. Önbellekte girdilerin boyutunu ölçen bir mekanizma olmadığından önbellek boyutu sınırı tanımlı bir ölçü birimine sahip değildir. Önbellek boyutu sınırı ayarlanırsa, tüm girdilerin boyutu belirtmesi gerekir. ASP.NET Core çalışma zamanı, bellek baskısına bağlı olarak önbellek boyutunu sınırlamaz. Önbellek boyutunu sınırlamak geliştiriciye bağlı. Belirtilen boyut, geliştiricinin seçtiği birim cinsindendir.
Örneğin:
- Web uygulaması birincil olarak dizeleri önbelleğe almaksa, her önbellek girdisi boyutu dize uzunluğu olabilir.
- Uygulama tüm girişlerin boyutunu 1 olarak belirtebilir ve boyut sınırı girdi sayısıdır.
SizeLimit Ayarlanmadıysa, önbellek bağlı olmadan büyür. ASP.NET Core çalışma zamanı, sistem belleği düşük olduğunda önbelleği kırpmaz. Uygulamaların mimarisinin şu şekilde tasarlanması gerekir:
Aşağıdaki kod, bağımlılık ekleme ile erişilebilen bir birimsiz sabit boyut MemoryCache oluşturur:
public class MyMemoryCache
{
public MemoryCache Cache { get; } = new MemoryCache(
new MemoryCacheOptions
{
SizeLimit = 1024
});
}
SizeLimit
birimleri yoktur. Önbellek boyutu sınırı ayarlandıysa, önbelleğe alınan girdilerin boyutu en uygun olarak değerlendirdikleri birimlerde belirtmesi gerekir. Önbellek örneğinin tüm kullanıcıları aynı birim sistemini kullanmalıdır. Önbelleğe alınan girdi boyutlarının toplamı tarafından SizeLimit
belirtilen değeri aşarsa bir girdi önbelleğe alınmaz. Önbellek boyutu sınırı ayarlı değilse, girdide ayarlanan önbellek boyutu yoksayılır.
Aşağıdaki kod bağımlılık ekleme kapsayıcısıyla kaydolurMyMemoryCache
:
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddSingleton<MyMemoryCache>();
MyMemoryCache
, bu boyut sınırlı önbelleğin farkında olan ve önbellek giriş boyutunu uygun şekilde ayarlamayı bilen bileşenler için bağımsız bir bellek önbelleği olarak oluşturulur.
Önbellek girdisinin boyutu, uzantı yöntemi veya Size özelliği kullanılarak SetSize ayarlanabilir:
if (!_myMemoryCache.Cache.TryGetValue(CacheKeys.Entry, out DateTime cacheValue))
{
var cacheEntryOptions = new MemoryCacheEntryOptions()
.SetSize(1);
// cacheEntryOptions.Size = 1;
_myMemoryCache.Cache.Set(CacheKeys.Entry, cacheValue, cacheEntryOptions);
}
Yukarıdaki kodda vurgulanan iki satır, önbellek girdisinin boyutunun ayarlanmasıyla aynı sonucu elde ediyor. SetSize
, çağrıları üzerine new MemoryCacheOptions()
zincirleme sırasında kolaylık sağlamak için sağlanır.
MemoryCache.Compact
MemoryCache.Compact
önbelleğin belirtilen yüzdesini aşağıdaki sırayla kaldırmaya çalışır:
- Süresi dolan tüm öğeler.
- Önceliğe göre öğeler. En düşük öncelikli öğeler önce kaldırılır.
- En son kullanılan nesneler.
- En erken mutlak süre sonu olan öğeler.
- En erken kayan süre sonu olan öğeler.
Önceliğe NeverRemove sahip sabitlenmiş öğeler hiçbir zaman kaldırılmaz. Aşağıdaki kod bir önbellek öğesini kaldırır ve önbelleğe alınan girdilerin %25'ini kaldırmak için çağrı Compact
yapar:
_myMemoryCache.Cache.Remove(CacheKeys.Entry);
_myMemoryCache.Cache.Compact(.25);
Daha fazla bilgi için bkz. GitHub'da sıkıştırma kaynağı.
Önbellek bağımlılıkları
Aşağıdaki örnekte, bağımlı bir girişin süresi dolarsa önbellek girdisinin süresinin nasıl dolmasına neden olduğu gösterilmektedir. Önbelleğe alınan öğeye bir CancellationChangeToken eklenir. üzerinde CancellationTokenSource
çağrıldığındaCancel
, her iki önbellek girdisi de çıkarılır:
public void OnGetCacheCreateDependent()
{
var cancellationTokenSource = new CancellationTokenSource();
_memoryCache.Set(
CacheKeys.DependentCancellationTokenSource,
cancellationTokenSource);
using var parentCacheEntry = _memoryCache.CreateEntry(CacheKeys.Parent);
parentCacheEntry.Value = DateTime.Now;
_memoryCache.Set(
CacheKeys.Child,
DateTime.Now,
new CancellationChangeToken(cancellationTokenSource.Token));
}
public void OnGetCacheRemoveDependent()
{
var cancellationTokenSource = _memoryCache.Get<CancellationTokenSource>(
CacheKeys.DependentCancellationTokenSource);
cancellationTokenSource.Cancel();
}
kullanarak CancellationTokenSource birden çok önbellek girdisi grup olarak çıkarılabilir. using
Yukarıdaki koddaki desenle, kapsam içinde using
oluşturulan önbellek girdileri tetikleyicileri ve süre sonu ayarlarını devralır.
Ek notlar
Süre sonu arka planda gerçekleşmez. Süresi dolan öğeler için önbelleği etkin bir şekilde tarayan zamanlayıcı yoktur. Önbellekteki herhangi bir etkinlik (
Get
,Set
,Remove
) süresi dolan öğeler için arka plan taraması tetikleyebilir. (CancelAfter) üzerindekiCancellationTokenSource
bir zamanlayıcı da girdiyi kaldırır ve süresi dolan öğeler için bir tarama tetikler. Aşağıdaki örnekte kayıtlı belirteç için kullanılır CancellationTokenSource(TimeSpan) . Bu belirteç tetiklendiğinde, girişi hemen kaldırır ve çıkarma geri çağırmalarını başlatır:if (!_memoryCache.TryGetValue(CacheKeys.Entry, out DateTime cacheValue)) { cacheValue = DateTime.Now; var cancellationTokenSource = new CancellationTokenSource( TimeSpan.FromSeconds(10)); var cacheEntryOptions = new MemoryCacheEntryOptions() .AddExpirationToken( new CancellationChangeToken(cancellationTokenSource.Token)) .RegisterPostEvictionCallback((key, value, reason, state) => { ((CancellationTokenSource)state).Dispose(); }, cancellationTokenSource); _memoryCache.Set(CacheKeys.Entry, cacheValue, cacheEntryOptions); }
Önbellek öğesini yeniden doldurmaya yönelik bir geri çağırma kullanılırken:
- Geri çağırma tamamlanmadığından birden çok istek önbelleğe alınmış anahtar değerini boş bulabilir.
- Bu, önbelleğe alınan öğenin birkaç iş parçacığının yeniden doldurulmasıyla sonuçlanabilir.
Bir önbellek girdisi başka bir önbellek girişi oluşturmak için kullanıldığında, alt öğe üst girdinin süre sonu belirteçlerini ve zamana bağlı süre sonu ayarlarını kopyalar. Üst girişin el ile kaldırılması veya güncelleştirilmesiyle alt çocuğun süresi dolmaz.
Önbellek girdisi önbellekten çıkarıldıktan sonra tetiklenecek geri çağırmaları ayarlamak için kullanın PostEvictionCallbacks .
Çoğu uygulama
IMemoryCache
için etkindir. Örneğin, içinde , , , ve diğerAdd{Service}
birçok yöntemiProgram.cs
çağırmakAddMvc
öğesini etkinleştirirIMemoryCache
.AddMvcCore().AddRazorViewEngine
AddRazorPages
AddControllersWithViews
ÖncekiAdd{Service}
yöntemlerden birini çağırmamış uygulamalar için içinde çağrısı AddMemoryCacheProgram.cs
yapılması gerekebilir.
Arka plan önbelleği güncelleştirmesi
Önbelleği güncelleştirmek için gibi IHostedService bir arka plan hizmeti kullanın. Arka plan hizmeti girdileri yeniden derleyebilir ve sonra bunları yalnızca hazır olduklarında önbelleğe atayabilir.
Ek kaynaklar
- Örnek kodu görüntüleme veya indirme (indirme)
- ASP.NET Core'da dağıtılmış önbelleğe alma
- ASP.NET Core'da değişiklik belirteçleriyle değişiklikleri algılama
- ASP.NET Core'da yanıtı önbelleğe alma
- ASP.NET Core'da Yanıt Önbelleğe Alma Ara Yazılımı
- ASP.NET Core MVC'de Önbellek Etiketi Yardımcısı
- ASP.NET Core'da Dağıtılmış Önbellek Etiketi Yardımcısı
Örnek kodu görüntüleme veya indirme (indirme)
temel Önbelleğe Alma
Önbelleğe Alma, içerik oluşturmak için gereken çalışmayı azaltarak uygulamanın performansını ve ölçeklenebilirliğini önemli ölçüde geliştirebilir. Önbelleğe Alma, seyrek değişen ve oluşturulması pahalı olan verilerle en iyi şekilde çalışır. Önbelleğe Alma, kaynaktan çok daha hızlı döndürülebilecek verilerin bir kopyasını oluşturur. Uygulamalar hiçbir zaman önbelleğe alınmış verilere bağımlı olmayacak şekilde yazılmalı ve test edilmelidir.
ASP.NET Core birkaç farklı önbelleği destekler. En basit önbellek temel alır IMemoryCache. IMemoryCache
, web sunucusunun belleğinde depolanan bir önbelleği temsil eder. Bir sunucu grubunda (birden çok sunucu) çalışan uygulamalar, bellek içi önbelleği kullanırken oturumların yapışkan olmasını sağlamalıdır. Yapışkan oturumlar, bir istemciden gelen sonraki isteklerin tümünün aynı sunucuya gitmesini sağlar. Örneğin, Azure Web uygulamaları sonraki tüm istekleri aynı sunucuya yönlendirmek için Uygulama İsteği Yönlendirmesi'ni (ARR) kullanır.
Web grubundaki yapışkan olmayan oturumlar, önbellek tutarlılığı sorunlarını önlemek için dağıtılmış bir önbellek gerektirir. Bazı uygulamalarda, dağıtılmış önbellek bellek içi önbellekten daha yüksek ölçeği genişletmeyi destekleyebilir. Dağıtılmış önbellek kullanmak, önbellek belleğini bir dış işleme boşaltır.
Bellek içi önbellek herhangi bir nesneyi depolayabilir. Dağıtılmış önbellek arabirimi ile byte[]
sınırlıdır. Bellek içi ve dağıtılmış önbellek deposu önbellek öğelerini anahtar-değer çiftleri olarak depolar.
Runtime. Önbelleğe Alma/MemoryCache
System.Runtime.Caching/MemoryCache (NuGet paketi) ile kullanılabilir:
- .NET Standard 2.0 veya üzeri.
- .NET Standard 2.0 veya üstünü hedefleyen herhangi bir .NET uygulaması . Örneğin, Core 3.1 veya sonraki bir sürümü ASP.NET.
- .NET Framework 4.5 veya üzeri.
Microsoft.Extensions. Önbelleğe Alma. ASP.NET Core ile daha iyi tümleştirildiğinden bellek/IMemoryCache
(bu makalede açıklanmıştırSystem.Runtime.Caching
/MemoryCache
) önerilir. Örneğin, IMemoryCache
ASP.NET Core bağımlılık ekleme ile yerel olarak çalışır.
kodu ASP.NET 4.x'ten ASP.NET Core'a aktarırken uyumluluk köprüsü olarak kullanın System.Runtime.Caching
/MemoryCache
.
Önbellek yönergeleri
- Kod her zaman verileri getirmek için bir geri dönüş seçeneğine sahip olmalı ve önbelleğe alınmış bir değerin kullanılabilir olmasına bağlı olmamalıdır .
- Önbellekte az miktarda kaynak ve bellek kullanılır. Önbellek büyümesini sınırla:
- Önbellek anahtarları olarak dış giriş kullanmayın.
- Önbellek büyümesini sınırlamak için süre sonu kullanma.
- Önbellek boyutunu sınırlamak için SetSize, Size ve SizeLimit kullanın. ASP.NET Core çalışma zamanı, bellek baskısına bağlı olarak önbellek boyutunu sınırlamaz. Önbellek boyutunu sınırlamak geliştiriciye bağlı.
IMemoryCache kullanma
Uyarı
Bağımlılık Ekleme'den paylaşılan bir bellek önbelleği kullanmak ve önbellek boyutunu sınırlamak için , Size
veya SizeLimit
çağrısı SetSize
yapmak uygulamanın başarısız olmasına neden olabilir. Önbellekte boyut sınırı ayarlandığında, tüm girdiler eklenirken bir boyut belirtmelidir. Geliştiriciler paylaşılan önbelleği kullananlar üzerinde tam denetime sahip olmadığından bu sorunlara yol açabilir.
Önbelleği sınırlamak için , Size
veya SizeLimit
kullanırkenSetSize
, önbelleğe alma için bir önbellek teklisi oluşturun. Daha fazla bilgi ve örnek için bkz . Önbellek boyutunu sınırlamak için SetSize, Size ve SizeLimit kullanma.
Paylaşılan önbellek, diğer çerçeveler veya kitaplıklar tarafından paylaşılan önbellektir.
Bellek içi önbelleğe alma, Bağımlılık Ekleme kullanılarak bir uygulamadan başvuruda bulunan bir hizmettir. Oluşturucudaki IMemoryCache
örneği isteyin:
public class HomeController : Controller
{
private IMemoryCache _cache;
public HomeController(IMemoryCache memoryCache)
{
_cache = memoryCache;
}
Aşağıdaki kod, bir saatin önbellekte olup olmadığını denetlemek için kullanır TryGetValue . Bir zaman önbelleğe alınmazsa yeni bir giriş oluşturulur ve ile Setönbelleğe eklenir. CacheKeys
sınıfı, indirme örneğinin bir parçasıdır.
public static class CacheKeys
{
public static string Entry => "_Entry";
public static string CallbackEntry => "_Callback";
public static string CallbackMessage => "_CallbackMessage";
public static string Parent => "_Parent";
public static string Child => "_Child";
public static string DependentMessage => "_DependentMessage";
public static string DependentCTS => "_DependentCTS";
public static string Ticks => "_Ticks";
public static string CancelMsg => "_CancelMsg";
public static string CancelTokenSource => "_CancelTokenSource";
}
public IActionResult CacheTryGetValueSet()
{
DateTime cacheEntry;
// Look for cache key.
if (!_cache.TryGetValue(CacheKeys.Entry, out cacheEntry))
{
// Key not in cache, so get data.
cacheEntry = DateTime.Now;
// Set cache options.
var cacheEntryOptions = new MemoryCacheEntryOptions()
// Keep in cache for this time, reset time if accessed.
.SetSlidingExpiration(TimeSpan.FromSeconds(3));
// Save data in cache.
_cache.Set(CacheKeys.Entry, cacheEntry, cacheEntryOptions);
}
return View("Cache", cacheEntry);
}
Geçerli saat ve önbelleğe alınan süre görüntülenir:
@model DateTime?
<div>
<h2>Actions</h2>
<ul>
<li><a asp-controller="Home" asp-action="CacheTryGetValueSet">TryGetValue and Set</a></li>
<li><a asp-controller="Home" asp-action="CacheGet">Get</a></li>
<li><a asp-controller="Home" asp-action="CacheGetOrCreate">GetOrCreate</a></li>
<li><a asp-controller="Home" asp-action="CacheGetOrCreateAsynchronous">CacheGetOrCreateAsynchronous</a></li>
<li><a asp-controller="Home" asp-action="CacheRemove">Remove</a></li>
<li><a asp-controller="Home" asp-action="CacheGetOrCreateAbs">CacheGetOrCreateAbs</a></li>
<li><a asp-controller="Home" asp-action="CacheGetOrCreateAbsSliding">CacheGetOrCreateAbsSliding</a></li>
</ul>
</div>
<h3>Current Time: @DateTime.Now.TimeOfDay.ToString()</h3>
<h3>Cached Time: @(Model == null ? "No cached entry found" : Model.Value.TimeOfDay.ToString())</h3>
Aşağıdaki kod, nesnesini oluşturmadan MemoryCacheEntryOptions
verileri göreli bir süre için önbelleğe almak için uzantı yöntemini kullanırSet
:
public IActionResult SetCacheRelativeExpiration()
{
DateTime cacheEntry;
// Look for cache key.
if (!_cache.TryGetValue(CacheKeys.Entry, out cacheEntry))
{
// Key not in cache, so get data.
cacheEntry = DateTime.Now;
// Save data in cache and set the relative expiration time to one day
_cache.Set(CacheKeys.Entry, cacheEntry, TimeSpan.FromDays(1));
}
return View("Cache", cacheEntry);
}
Zaman aşımı süresi içinde istekler olduğunda önbelleğe alınan DateTime
değer önbellekte kalır.
Aşağıdaki kod, verileri önbelleğe almak için ve GetOrCreateAsync kullanırGetOrCreate.
public IActionResult CacheGetOrCreate()
{
var cacheEntry = _cache.GetOrCreate(CacheKeys.Entry, entry =>
{
entry.SlidingExpiration = TimeSpan.FromSeconds(3);
return DateTime.Now;
});
return View("Cache", cacheEntry);
}
public async Task<IActionResult> CacheGetOrCreateAsynchronous()
{
var cacheEntry = await
_cache.GetOrCreateAsync(CacheKeys.Entry, entry =>
{
entry.SlidingExpiration = TimeSpan.FromSeconds(3);
return Task.FromResult(DateTime.Now);
});
return View("Cache", cacheEntry);
}
Önbelleğe alınmış zamanı getirmek için aşağıdaki kod çağrıları Get :
public IActionResult CacheGet()
{
var cacheEntry = _cache.Get<DateTime?>(CacheKeys.Entry);
return View("Cache", cacheEntry);
}
Aşağıdaki kod, mutlak süre sonuyla önbelleğe alınmış bir öğe alır veya oluşturur:
public IActionResult CacheGetOrCreateAbs()
{
var cacheEntry = _cache.GetOrCreate(CacheKeys.Entry, entry =>
{
entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(10);
return DateTime.Now;
});
return View("Cache", cacheEntry);
}
Yalnızca kayan süre sonu olan önbelleğe alınmış bir öğe kümesinin süresi hiç dolmama riski altındadır. Önbelleğe alınan öğeye kayan süre sonu aralığı içinde tekrar tekrar erişilirse, öğenin süresi hiçbir zaman dolmaz. Öğenin süresinin dolduğundan emin olmak için kayan süre sonunu mutlak süre sonuyla birleştirin. Mutlak süre sonu, öğenin ne kadar süre önbelleğe alınabileceğine ilişkin bir üst sınır ayarlar ve kayan süre sonu aralığı içinde istenmezse öğenin süresinin daha erken dolmasına izin verir. Kayan süre sonu aralığı veya mutlak süre sonu süresi geçerse, öğe önbellekten çıkarılır.
Aşağıdaki kod hem kayan hem de mutlak süre sonu olan önbelleğe alınmış bir öğe alır veya oluşturur:
public IActionResult CacheGetOrCreateAbsSliding()
{
var cacheEntry = _cache.GetOrCreate(CacheKeys.Entry, entry =>
{
entry.SetSlidingExpiration(TimeSpan.FromSeconds(3));
entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(20);
return DateTime.Now;
});
return View("Cache", cacheEntry);
}
Yukarıdaki kod, verilerin mutlak süreden daha uzun süre önbelleğe alınmayacağını garanti eder.
GetOrCreate, GetOrCreateAsyncve Get sınıfındaki CacheExtensions uzantı yöntemleridir. Bu yöntemler, özelliğini genişletir IMemoryCache.
MemoryCacheEntryOptions
Aşağıdaki örnek:
- Kayan süre sonu süresini ayarlar. Önbelleğe alınan bu öğeye erişen istekler kayan süre sonu saatini sıfırlar.
- Önbellek önceliğini olarak CacheItemPriority.NeverRemoveayarlar.
- Girdi önbellekten çıkarıldıktan sonra çağrılacak bir PostEvictionDelegate ayarlar. Geri çağırma, öğeyi önbellekten kaldıran koddan farklı bir iş parçacığında çalıştırılır.
public IActionResult CreateCallbackEntry()
{
var cacheEntryOptions = new MemoryCacheEntryOptions()
// Pin to cache.
.SetPriority(CacheItemPriority.NeverRemove)
// Add eviction callback
.RegisterPostEvictionCallback(callback: EvictionCallback, state: this);
_cache.Set(CacheKeys.CallbackEntry, DateTime.Now, cacheEntryOptions);
return RedirectToAction("GetCallbackEntry");
}
public IActionResult GetCallbackEntry()
{
return View("Callback", new CallbackViewModel
{
CachedTime = _cache.Get<DateTime?>(CacheKeys.CallbackEntry),
Message = _cache.Get<string>(CacheKeys.CallbackMessage)
});
}
public IActionResult RemoveCallbackEntry()
{
_cache.Remove(CacheKeys.CallbackEntry);
return RedirectToAction("GetCallbackEntry");
}
private static void EvictionCallback(object key, object value,
EvictionReason reason, object state)
{
var message = $"Entry was evicted. Reason: {reason}.";
((HomeController)state)._cache.Set(CacheKeys.CallbackMessage, message);
}
Önbellek boyutunu sınırlamak için SetSize, Size ve SizeLimit kullanma
Bir MemoryCache
örnek isteğe bağlı olarak bir boyut sınırı belirtebilir ve zorunlu kılabilir. Önbellekte girdilerin boyutunu ölçecek bir mekanizma olmadığından önbellek boyutu sınırı tanımlı bir ölçü birimine sahip değildir. Önbellek boyutu sınırı ayarlanırsa, tüm girdilerin boyutu belirtmesi gerekir. ASP.NET Core çalışma zamanı, önbellek boyutunu bellek baskısına göre sınırlamaz. Önbellek boyutunu sınırlamak geliştiriciye bağlı. Belirtilen boyut, geliştiricinin seçtiği birim cinsindendir.
Örneğin:
- Web uygulaması birincil olarak dizeleri önbelleğe almaksa, her önbellek girdisi boyutu dize uzunluğu olabilir.
- Uygulama tüm girişlerin boyutunu 1 olarak belirtebilir ve boyut sınırı girdi sayısıdır.
SizeLimit Ayarlanmadıysa, önbellek bağlı olmadan büyür. ASP.NET Core çalışma zamanı, sistem belleği düşük olduğunda önbelleği kırpmaz. Uygulamaların mimarisinin şu şekilde tasarlanması gerekir:
Aşağıdaki kod, bağımlılık ekleme ile erişilebilen bir birimsiz sabit boyut MemoryCache oluşturur:
// using Microsoft.Extensions.Caching.Memory;
public class MyMemoryCache
{
public MemoryCache Cache { get; private set; }
public MyMemoryCache()
{
Cache = new MemoryCache(new MemoryCacheOptions
{
SizeLimit = 1024
});
}
}
SizeLimit
birimleri yoktur. Önbellek boyutu sınırı ayarlandıysa, önbelleğe alınan girdilerin boyutu en uygun gördükleri birimlerde belirtmesi gerekir. Önbellek örneğinin tüm kullanıcıları aynı birim sistemini kullanmalıdır. Önbelleğe alınan girdi boyutlarının toplamı tarafından SizeLimit
belirtilen değeri aşarsa bir girdi önbelleğe alınmaz. Önbellek boyutu sınırı ayarlı değilse, girdide ayarlanan önbellek boyutu yoksayılır.
Aşağıdaki kod bağımlılık ekleme kapsayıcısıyla kaydolurMyMemoryCache
.
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
services.AddSingleton<MyMemoryCache>();
}
MyMemoryCache
, bu boyut sınırlı önbelleğin farkında olan ve önbellek giriş boyutunu uygun şekilde ayarlamayı bilen bileşenler için bağımsız bir bellek önbelleği olarak oluşturulur.
Aşağıdaki kodda kullanılır MyMemoryCache
:
public class SetSize : PageModel
{
private MemoryCache _cache;
public static readonly string MyKey = "_MyKey";
public SetSize(MyMemoryCache memoryCache)
{
_cache = memoryCache.Cache;
}
[TempData]
public string DateTime_Now { get; set; }
public IActionResult OnGet()
{
if (!_cache.TryGetValue(MyKey, out string cacheEntry))
{
// Key not in cache, so get data.
cacheEntry = DateTime.Now.TimeOfDay.ToString();
var cacheEntryOptions = new MemoryCacheEntryOptions()
// Set cache entry size by extension method.
.SetSize(1)
// Keep in cache for this time, reset time if accessed.
.SetSlidingExpiration(TimeSpan.FromSeconds(3));
// Set cache entry size via property.
// cacheEntryOptions.Size = 1;
// Save data in cache.
_cache.Set(MyKey, cacheEntry, cacheEntryOptions);
}
DateTime_Now = cacheEntry;
return RedirectToPage("./Index");
}
}
Önbellek girdisinin boyutu veya SetSize uzantı yöntemleri tarafından Size ayarlanabilir:
public IActionResult OnGet()
{
if (!_cache.TryGetValue(MyKey, out string cacheEntry))
{
// Key not in cache, so get data.
cacheEntry = DateTime.Now.TimeOfDay.ToString();
var cacheEntryOptions = new MemoryCacheEntryOptions()
// Set cache entry size by extension method.
.SetSize(1)
// Keep in cache for this time, reset time if accessed.
.SetSlidingExpiration(TimeSpan.FromSeconds(3));
// Set cache entry size via property.
// cacheEntryOptions.Size = 1;
// Save data in cache.
_cache.Set(MyKey, cacheEntry, cacheEntryOptions);
}
DateTime_Now = cacheEntry;
return RedirectToPage("./Index");
}
MemoryCache.Compact
MemoryCache.Compact
önbelleğin belirtilen yüzdesini aşağıdaki sırayla kaldırmaya çalışır:
- Süresi dolan tüm öğeler.
- Önceliğe göre öğeler. En düşük öncelikli öğeler önce kaldırılır.
- En son kullanılan nesneler.
- En erken mutlak süre sonu olan öğeler.
- En erken kayan süre sonu olan öğeler.
Önceliğe NeverRemove sahip sabitlenmiş öğeler hiçbir zaman kaldırılmaz. Aşağıdaki kod bir önbellek öğesini kaldırır ve öğesini çağırır Compact
:
_cache.Remove(MyKey);
// Remove 33% of cached items.
_cache.Compact(.33);
cache_size = _cache.Count;
Daha fazla bilgi için bkz. GitHub'da sıkıştırma kaynağı.
Önbellek bağımlılıkları
Aşağıdaki örnekte, bağımlı bir girişin süresi dolarsa önbellek girdisinin süresinin nasıl dolmasına neden olduğu gösterilmektedir. Önbelleğe alınan öğeye bir CancellationChangeToken eklenir. üzerinde CancellationTokenSource
çağrıldığındaCancel
, her iki önbellek girdisi de çıkarılır.
public IActionResult CreateDependentEntries()
{
var cts = new CancellationTokenSource();
_cache.Set(CacheKeys.DependentCTS, cts);
using (var entry = _cache.CreateEntry(CacheKeys.Parent))
{
// expire this entry if the dependant entry expires.
entry.Value = DateTime.Now;
entry.RegisterPostEvictionCallback(DependentEvictionCallback, this);
_cache.Set(CacheKeys.Child,
DateTime.Now,
new CancellationChangeToken(cts.Token));
}
return RedirectToAction("GetDependentEntries");
}
public IActionResult GetDependentEntries()
{
return View("Dependent", new DependentViewModel
{
ParentCachedTime = _cache.Get<DateTime?>(CacheKeys.Parent),
ChildCachedTime = _cache.Get<DateTime?>(CacheKeys.Child),
Message = _cache.Get<string>(CacheKeys.DependentMessage)
});
}
public IActionResult RemoveChildEntry()
{
_cache.Get<CancellationTokenSource>(CacheKeys.DependentCTS).Cancel();
return RedirectToAction("GetDependentEntries");
}
private static void DependentEvictionCallback(object key, object value,
EvictionReason reason, object state)
{
var message = $"Parent entry was evicted. Reason: {reason}.";
((HomeController)state)._cache.Set(CacheKeys.DependentMessage, message);
}
kullanarak CancellationTokenSource birden çok önbellek girdisi grup olarak çıkarılabilir. using
Yukarıdaki koddaki desenle, bloğun using
içinde oluşturulan önbellek girdileri tetikleyicileri ve süre sonu ayarlarını devralır.
Ek notlar
Süre sonu arka planda gerçekleşmez. Süresi dolan öğeler için önbelleği etkin bir şekilde tarar zamanlayıcı yoktur. Önbellekteki herhangi bir etkinlik (
Get
,Set
,Remove
) süresi dolan öğeler için arka plan taraması tetikleyebilir. (CancelAfter) üzerindekiCancellationTokenSource
bir zamanlayıcı da girdiyi kaldırır ve süresi dolan öğeler için bir tarama tetikler. Aşağıdaki örnekte kayıtlı belirteç için kullanılır CancellationTokenSource(TimeSpan) . Bu belirteç tetiklendiğinde girişi hemen kaldırır ve çıkarma geri çağırmalarını başlatır:public IActionResult CacheAutoExpiringTryGetValueSet() { DateTime cacheEntry; if (!_cache.TryGetValue(CacheKeys.Entry, out cacheEntry)) { cacheEntry = DateTime.Now; var cts = new CancellationTokenSource(TimeSpan.FromSeconds(10)); var cacheEntryOptions = new MemoryCacheEntryOptions() .AddExpirationToken(new CancellationChangeToken(cts.Token)); _cache.Set(CacheKeys.Entry, cacheEntry, cacheEntryOptions); } return View("Cache", cacheEntry); }
Önbellek öğesini yeniden doldurmaya yönelik bir geri çağırma kullanılırken:
- Geri çağırma tamamlanmadığından birden çok istek önbelleğe alınmış anahtar değerini boş bulabilir.
- Bu, önbelleğe alınan öğenin birkaç iş parçacığının yeniden doldurulmasıyla sonuçlanabilir.
Bir önbellek girdisi başka bir önbellek girişi oluşturmak için kullanıldığında, alt öğe üst girdinin süre sonu belirteçlerini ve zamana bağlı süre sonu ayarlarını kopyalar. Üst girişin el ile kaldırılması veya güncelleştirilmesiyle alt çocuğun süresi dolmaz.
Önbellek girdisi önbellekten çıkarıldıktan sonra tetiklenecek geri çağırmaları ayarlamak için kullanın PostEvictionCallbacks . Örnek kodda, CancellationTokenSource.Dispose() tarafından kullanılan yönetilmeyen kaynakları serbest bırakmak için çağrılır
CancellationTokenSource
. Ancak, önbellek girdisiCancellationTokenSource
tarafından kullanılmaya devam ettiğinden hemen atılmaz.CancellationToken
, belirli bir süre sonra süresi dolan bir önbellek girdisi oluşturmak için öğesine geçirilirMemoryCacheEntryOptions
. Bu nedenleDispose
, önbellek girdisi kaldırılana veya süresi dolana kadar çağrılmamalıdır. Örnek kod, önbellek girdisi çıkarıldığında çağrılacak bir geri çağırmayı kaydetmek için yöntemini çağırır RegisterPostEvictionCallback ve bu geri çağırmaya atılırCancellationTokenSource
.Çoğu uygulama
IMemoryCache
için etkindir. Örneğin, içinde , , , ve diğerAdd{Service}
birçok yöntemiConfigureServices
çağırmakAddMvc
öğesini etkinleştirirIMemoryCache
.AddMvcCore().AddRazorViewEngine
AddRazorPages
AddControllersWithViews
ÖncekiAdd{Service}
yöntemlerden birini çağırmayan uygulamalar için içinde çağrısı AddMemoryCacheConfigureServices
yapılması gerekebilir.
Arka plan önbelleği güncelleştirmesi
Önbelleği güncelleştirmek için gibi IHostedService bir arka plan hizmeti kullanın. Arka plan hizmeti girdileri yeniden derleyebilir ve sonra bunları yalnızca hazır olduklarında önbelleğe atayabilir.
Ek kaynaklar
ASP.NET Core