Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
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 artırabilir. Ö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ülebilen 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 IMemoryCache üzerine kuruludur.
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 byte[]
ile sınırlıdır. Bellek içi ve dağıtılmış önbellek deposu önbellek öğelerini anahtar-değer çiftleri olarak depolar.
System.Runtime.Caching/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, ASP.NET Core 3.1 veya daha yeni bir sürümü.
- .NET Framework 4.5 veya üzeri.
Microsoft.Extensions.Caching.Memory/IMemoryCache
(bu makalede açıklanmıştır), ASP.NET Core ile daha iyi tümleştirildiğinden System.Runtime.Caching
/MemoryCache
önerilir. Örneğin, IMemoryCache
ASP.NET Core bağımlılık enjeksiyonu ile doğal 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 göre önbellek boyutunu sınırlamaz . Önbellek boyutunu sınırlamak geliştiriciye bağlı.
IMemoryCache kullanma
Uyarı
Paylaşılan bir bellek önbelleğini Bağımlılık Enjeksiyonu ile kullanmak ve önbellek boyutunu sınırlamak için SetSize
, Size
veya SizeLimit
çağrısı 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 SetSize
, Size
veya SizeLimit
kullanırken, önbelleğe alma için bir önbellek singletonu 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 Enjeksiyonu kullanılarak bir uygulamadan referans verilen 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 . Eğer bir zaman önbelleğe alınmamışsa, yeni bir giriş oluşturulur ve Set ile ö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, Set
uzantı yöntemini kullanarak MemoryCacheEntryOptions
olmadan, verileri göreli bir süre için önbelleğe alır:
_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 GetOrCreate ve GetOrCreateAsync kullanır.
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 Get'yi çağırır:
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 öğeyi alır ve 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, IMemoryCache'ün yeteneğini genişletir.
MemoryCacheEntryOptions
Aşağıdaki örnek:
- Önbellek önceliğini CacheItemPriority.NeverRemove olarak ayarlar.
- 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 sınırsız 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 kodMemoryCache ile erişilebilen bir birimsiz sabit boyut 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 MyMemoryCache
'yi bağımlılık ekleme kapsayıcısına kaydeder:
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 SetSize özelliği kullanılarak Size 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ın new MemoryCacheOptions()
ile zincirleme şekilde yapılabilmesi için kolaylık sağlar.
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 az yakın zamanda 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ınmış girdilerin 25% kaldırmayı çağırır Compact
:
_myMemoryCache.Cache.Remove(CacheKeys.Entry);
_myMemoryCache.Cache.Compact(.25);
Daha fazla bilgi için GitHub'daki Compact kaynağına bakın.
Önbellek bağımlılıkları
Aşağıdaki örnek, bağımlı bir girişin süresi dolduğunda önbellek girişinin nasıl sona erdirileceğini gösterir. Önbelleğe alınan öğeye bir CancellationChangeToken eklenir.
Cancel
üzerinde CancellationTokenSource
çağrıldığında, 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();
}
Bir CancellationTokenSource kullanarak birden çok önbellek girdisi grup olarak kaldırılabilir.
using
Yukarıdaki koddaki desenle, using
kapsamı içinde oluşturulan önbellek girdileri tetikleyicileri ve süre sonu ayarlarını devralır.
Ek notlar
Süresinin dolması 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
,TryGetValue
,Set
,Remove
) süresi dolan öğeler için arka plan taraması tetikleyebilir.CancellationTokenSource
(CancelAfter) üzerindeki bir zamanlayıcı, aynı zamanda 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 jeton tetiklendiğinde, kaydı hemen kaldırır ve geriye çağırma işlevlerini çalıştırı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ınmış öğeyi birkaç iş parçacığının yeniden doldurması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. Ebeveyn girişinin el ile kaldırılması veya güncellenmesiyle çocuğun süresi dolmaz.
Önbellek girdisi önbellekten çıkarıldıktan sonra tetiklenecek geri çağırmaları ayarlamak için kullanın PostEvictionCallbacks .
Çoğu uygulamada
IMemoryCache
etkindir. Örneğin,AddMvc
,AddControllersWithViews
,AddRazorPages
,AddMvcCore().AddRazorViewEngine
ve birçok başkaAdd{Service}
yöntemininProgram.cs
içinde çağrılmasıIMemoryCache
öğesini etkinleştirir. ÖncekiAdd{Service}
yöntemlerinden birini çağırmayan uygulamalar için, AddMemoryCache içindeProgram.cs
çağrısı yapılması gerekebilir.
Arka plan önbelleği güncelleştirmesi
Önbelleği güncelleştirmek için gibi bir IHostedService 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)
Önbelleğe almayla ilgili temel bilgiler
Önbelleğe alma, içerik oluşturmak için gereken çalışmayı azaltarak uygulamanın performansını ve ölçeklenebilirliğini önemli ölçüde artırabilir. Ö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ülebilen 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 IMemoryCache üzerine kuruludur.
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 byte[]
ile sınırlıdır. Bellek içi ve dağıtılmış önbellek deposu önbellek öğelerini anahtar-değer çiftleri olarak depolar.
System.Runtime.Caching/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, ASP.NET Core 3.1 veya daha yeni bir sürümü.
- .NET Framework 4.5 veya üzeri.
Microsoft.Extensions.Caching.Memory/IMemoryCache
(bu makalede açıklanmıştır), ASP.NET Core ile daha iyi tümleştirildiğinden System.Runtime.Caching
/MemoryCache
önerilir. Örneğin, IMemoryCache
ASP.NET Core bağımlılık enjeksiyonu ile doğal 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:
- Dış girişleri önbellek anahtarı olarak 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 göre önbellek boyutunu sınırlamaz . Önbellek boyutunu sınırlamak geliştiriciye bağlı.
IMemoryCache kullanma
Uyarı
Paylaşılan bir bellek önbelleğini Bağımlılık Enjeksiyonu ile kullanmak ve önbellek boyutunu sınırlamak için SetSize
, Size
veya SizeLimit
çağrısı 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 SetSize
, Size
veya SizeLimit
kullanırken, önbelleğe alma için bir önbellek singletonu 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 Enjeksiyonu kullanılarak bir uygulamadan referans verilen 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 Set ile ö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, Set
uzantı yöntemini kullanarak, MemoryCacheEntryOptions
nesnesini oluşturmadan, verileri göreli bir süre için önbelleğe alır:
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 GetOrCreate ve GetOrCreateAsync kullanır.
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 Get'yi çağırır:
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 öğeyi alır ve 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, IMemoryCache'ün yeteneğini genişletir.
MemoryCacheEntryOptions
Aşağıdaki örnek:
- Kayan son kullanma süresini ayarlar. Önbelleğe alınan bu öğeye erişen istekler kayan süre sonu saatini sıfırlar.
- Önbellek önceliğini CacheItemPriority.NeverRemove olarak ayarlar.
- 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 sınırsız 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 kodMemoryCache ile erişilebilen bir birimsiz sabit boyut 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, MyMemoryCache
ile bağımlılık enjeksiyonu kapsayıcısına kaydolur.
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, Size veya SetSize uzantı yöntemleri ile 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 az yakın zamanda 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 Compact
'i çağırır.
_cache.Remove(MyKey);
// Remove 33% of cached items.
_cache.Compact(.33);
cache_size = _cache.Count;
Daha fazla bilgi için GitHub'daki Compact kaynağına bakın.
Önbellek bağımlılıkları
Aşağıdaki örnek, bağımlı bir girişin süresi dolduğunda önbellek girişinin nasıl sona erdirileceğini gösterir. Önbelleğe alınan öğeye bir CancellationChangeToken eklenir.
Cancel
üzerinde CancellationTokenSource
çağrıldığında, 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);
}
Bir CancellationTokenSource kullanarak birden çok önbellek girdisi grup olarak kaldırı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üresinin dolması 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.CancellationTokenSource
(CancelAfter) üzerindeki bir zamanlayıcı, aynı zamanda 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ınmış öğeyi birkaç iş parçacığının yeniden doldurması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. Ebeveyn girişinin el ile kaldırılması veya güncellenmesiyle ç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(),
CancellationTokenSource
tarafından kullanılan yönetilmeyen kaynakları serbest bırakmak için çağrılır. Ancak,CancellationTokenSource
hâlâ önbellek girdisi tarafından kullanıldığı için hemen atılmaz.CancellationToken
, belirli bir süre sonra süresi dolan bir önbellek girdisi oluşturmak içinMemoryCacheEntryOptions
öğesine iletilir. 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 RegisterPostEvictionCallback yöntemini çağırır ve bu geri çağırmadaCancellationTokenSource
'yi serbest bırakır.Çoğu uygulamada
IMemoryCache
etkindir. Örneğin,AddMvc
,AddControllersWithViews
,AddRazorPages
,AddMvcCore().AddRazorViewEngine
ve birçok başkaAdd{Service}
yöntemininConfigureServices
içinde çağrılmasıIMemoryCache
öğesini etkinleştirir. ÖncekiAdd{Service}
yöntemlerinden birini çağırmayan uygulamalar için, AddMemoryCache içindeConfigureServices
çağrısı yapılması gerekebilir.
Arka plan önbelleği güncelleştirmesi
Önbelleği güncelleştirmek için gibi bir IHostedService 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