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.
Bu makale, Microsoft.Identity.Web'deki belirteç önbelleği sorunlarını tanılamanıza ve çözmenize yardımcı olur. Belirteç önbelleği sorunları kimlik doğrulama hatalarına, performansın düşmesine veya beklenmeyen oturum açma istemlerine neden olabilir. Microsoft.Identity.Web'de belirteç önbelleğe almanın nasıl çalıştığı hakkında genel bir bakış için Token cache overview'a bakın.
Önkoşullar
Sorun gidermeden önce aşağıdakileri onaylayın:
- Microsoft.Identity.Web desteklenen bir sürümünü kullanıyorsunuz.
- Uygulamanızda
Program.csveyaStartup.csiçinde belirteç önbelleğe alma yapılandırılmış durumda. - Uygulama günlüklerine ve varsa dağıtılmış önbellek altyapınıza erişiminiz vardır.
Belirteç önbelleği günlüğünü ve tanılamayı etkinleştirme
İlk tanılama adımı olarak ayrıntılı kayıt tutmayı etkinleştirin. Microsoft Identity.Web, ASP.NET Core günlük altyapısını kullanır ve olayları Microsoft Authentication Library (MSAL) üzerinden yayar.
MSAL günlüğünü etkinleştirme
Kimlik kitaplıkları için günlük düzeyini Debug olarak appsettings.json içinde ayarlayın:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.Identity.Web": "Debug",
"Microsoft.IdentityModel": "Debug"
}
}
}
MSAL önbellek olaylarına abone olma
Önbellek isabetlerini, kaçırma durumlarını ve serileştirme etkinliğini izlemek için MSAL belirteci önbellek bildirim olaylarına abone olun.
services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(Configuration)
.EnableTokenAcquisitionToCallDownstreamApi()
.AddDistributedTokenCaches();
services.Configure<MsalDistributedTokenCacheAdapterOptions>(options =>
{
options.OnL2CacheFailure = (ex) =>
{
logger.LogWarning(ex, "L2 cache failure encountered.");
// Return true to allow the operation to continue despite the cache failure.
// Return false to propagate the exception.
return true;
};
});
Önbellek ölçümlerini izleme
Üretim izleme için şu önemli ölçümleri izleyin:
- Önbellek isabet oranı — düşük isabet oranı belirteçlerin önbellekten alınmıyor olduğunu gösterir.
- L2 önbellek gecikme süresi — yüksek gecikme süresi dağıtılmış önbellek bağlantısı veya performans sorununa işaret eder.
- Önbellek serileştirme hataları — okuma veya yazma sırasındaki hatalar bozulmayı veya sürüm uyuşmazlıklarını gösterir.
- Bellek tüketimi — sürekli büyüme eksik tahliye politikalarını gösterebilir.
Dağıtılmış önbellek (L2) bağlantı hataları
Belirti
Uygulama günlükleri bağlantı zaman aşımı hatalarını veya aralıklı kimlik doğrulama hatalarını gösterir. Kullanıcılar oturum açma gecikmeleriyle karşılaşır ve aşağıdakiler gibi özel durumlar görürsünüz:
Microsoft.Extensions.Caching.StackExchangeRedis.RedisCache:
StackExchange.Redis.RedisConnectionException:
No connection is active/available to service this operation.
Veya dağıtılmış SQL Server önbellek için:
Microsoft.Data.SqlClient.SqlException:
A network-related or instance-specific error occurred while
establishing a connection to SQL Server.
Nedeni
Dağıtılmış önbellek yedekleme deposuna (Redis veya SQL Server) ulaşılamıyor. Yaygın nedenler şunlardır:
- Yanlış bağlantı dizesi veya süresi dolmuş erişim kimlik bilgileri.
- Uygulama konağından bağlantıyı engelleyen ağ güvenlik duvarı kuralları.
- Önbellek hizmeti çalışmıyor veya bakımdan geçiyor.
- İstemci ve önbellek sunucusu arasında SSL/TLS yapılandırma uyuşmazlığı.
Tanılama adımları
Bağlantı hatasını belirlemek için şu adımları izleyin:
- Bağlantıyı doğrulayın. Uygulama konağından,
Test-NetConnection(PowerShell) veyaredis-clikullanarak Redis veya SQL Server bağlantısını test edin. - bağlantı dizesi denetleyin. Bağlantı dizesinin, önbellek sunucusunun ana bilgisayar adı, bağlantı noktası ve kimlik bilgileriyle eşleştiğinden emin olun.
- Güvenlik duvarı kurallarını gözden geçirin. Azure'da, uygulama hizmetinin veya sanal ağın önbellek kaynağına ulaşıp ulaşmadığını kontrol edin.
- Servis durumunu denetleyin. Azure portalında Redis için Azure Önbellek veya SQL Veritabanı örneğinizin sistem durumunu ve ölçümlerini gözden geçirin.
Çözüm
1. Adım: Bağlantı dizisini düzeltin
Bağlantı dizesini appsettings.json içinde doğrulayın.
{
"ConnectionStrings": {
"Redis": "your-redis-instance.redis.cache.windows.net:6380,password=your-access-key,ssl=True,abortConnect=False"
}
}
Önemli
abortConnect=False Redis bağlantı dizesini ayarlayın. Bu ayar, uygulamanın hemen atmak yerine geçici bağlantı hatalarından sonra otomatik olarak yeniden bağlanmasını sağlar.
2. Adım: Yeniden denemeyi ve dayanıklılığı yapılandırma
Dağıtılmış önbellek geçici olarak kullanılamadığında uygulamanızın sorunsuz bir şekilde çalışmaya devam edebilmesi için OnL2CacheFailure callback'i yapılandırın.
services.Configure<MsalDistributedTokenCacheAdapterOptions>(options =>
{
options.OnL2CacheFailure = (ex) =>
{
// Log the failure for monitoring and alerting.
logger.LogWarning(ex, "Distributed token cache is unavailable. " +
"Falling back to in-memory cache.");
return true; // Continue without the L2 cache.
};
// Set a timeout to avoid blocking the request pipeline.
options.AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(12);
});
3. Adım: Güvenlik duvarı kurallarını açma
Uygulama Azure App Service çalıştırılıyorsa ve önbellek bir sanal ağdaysa, App Service giden IP adreslerini önbellek güvenlik duvarı izin verme listesine ekleyin.
Önbellek seri durumdan çıkarma hataları
Belirti
Microsoft.Identity.Web veya MSAL.NET yükseltildikten sonra, uygulama dağıtılmış önbellekten okurken seri durumdan çıkarma hataları ile karşılaşıyor. Kullanıcıların yeniden oturum açması gerekir ve aşağıdaki gibi özel durumlar görürsünüz:
System.Text.Json.JsonException:
The JSON value could not be converted to the expected type.
Veya:
Microsoft.Identity.Client.MsalClientException:
Error code: json_parse_failed
Nedeni
Kitaplık sürümleri arasında belirteç önbelleği serileştirme biçimi değiştirildi. Önceki sürüm tarafından önbelleğe alınan belirteçler yeni sürüm tarafından seri durumdan çıkarılamaz. Bu sorun en sık, Microsoft.Identity.Web veya MSAL.NET'in ana sürüm yükseltmeleri sırasında ortaya çıkar.
Çözüm
A Seçeneği: Önbelleği temizleme
En basit düzeltme, dağıtılmış önbellekteki tüm girişleri temizlemektir. Kullanıcılar bir kez yeniden kimlik doğrulaması gerçekleştirir ve sonraki belirteçler yeni biçimde yazılır.
Redis önbelleğini temizleyin:
redis-cli FLUSHDB
Veya SQL Server dağıtılmış önbellek tablosunu temizleyin:
DELETE FROM [dbo].[TokenCache];
Uyarı
Önbelleğin temizlenmesi tüm etkin kullanıcıların yeniden kimlik doğrulamasına neden olur. Uygulamanız büyük bir kullanıcı tabanına hizmet verirse bu işlemi bir bakım penceresi sırasında planlayın.
Seçenek B: Deseriyalizasyon hatalarını düzgün bir şekilde işleme
Seri durumdan çıkarma hatalarını önemli hatalar yerine önbellek eksikleri olarak işlemek için önbellek bağdaştırıcısını yapılandırın:
services.Configure<MsalDistributedTokenCacheAdapterOptions>(options =>
{
options.OnL2CacheFailure = (ex) =>
{
if (ex is JsonException or MsalClientException)
{
logger.LogWarning(ex, "Cache deserialization failed. " +
"Treating as cache miss.");
return true;
}
return false; // Propagate unexpected errors.
};
});
Bu yaklaşımla, kullanıcılar yeniden kimlik doğrulaması yaptıkçe etkilenen önbellek girdileri otomatik olarak değiştirilir ve el ile önbellek temizleme gerekmez.
Sunucular arasında şifreleme anahtarı uyuşmazlığı
Belirti
Dağıtılmış önbellek çalışıyor olsa bile çok örnekli dağıtımlarda seri durumdan çıkarma hataları oluşur. Bir sunucu örneği tarafından önbelleğe alınan belirteçler başka bir sunucu örneği tarafından okunamaz. Günlüklerde json_parse_failed veya IDW10802 hataları görüyorsunuz.
Nedeni
Önbellek şifrelemesi etkinleştirildiğinde (options.Encrypt = true), Microsoft. Identity.Web, önbellek girdilerini şifrelemek için ASP.NET Core Data Protection kullanır. Varsayılan olarak, her sunucu örneği kendi Data Protection anahtarlarını oluşturur, bu nedenle bir örnek başka bir örnek tarafından yazılan girişlerin şifresini çözemez.
Çözüm
ASP.NET Core Data Protection'ı tüm sunucu örneklerinde şifreleme anahtarlarını paylaşacak şekilde yapılandırın.
Option A: Azure Blob Depolama + Azure Key Vault (Azure dağıtımlar için önerilir)
using Microsoft.AspNetCore.DataProtection;
using Azure.Identity;
builder.Services.AddDataProtection()
.PersistKeysToAzureBlobStorage(
new Uri("https://yourstorageaccount.blob.core.windows.net/dataprotection/keys.xml"),
new DefaultAzureCredential())
.ProtectKeysWithAzureKeyVault(
new Uri("https://yourkeyvault.vault.azure.net/keys/dataprotection-key"),
new DefaultAzureCredential());
builder.Services.Configure<MsalDistributedTokenCacheAdapterOptions>(options =>
{
options.Encrypt = true;
});
Bu yapılandırma, Data Protection anahtar grubunu Azure Blob Depolama'ta depolar ve depolanmış anahtarları Azure Key Vault ile korur. Aynı blob ve anahtara erişen tüm uygulama örnekleri, birbirlerinin önbellek girdilerini şifreleyebilir ve şifresini çözebilir.
Seçenek B: Sertifika koruması ile paylaşılan dosya sistemi
builder.Services.AddDataProtection()
.PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\keys"))
.ProtectKeysWithCertificate(certificate);
Tip
Data Protection sertifikasını döndürürken, hem geçerli hem de önceki sertifikaları eklemek için kullanın UnprotectKeysWithAnyCertificate . Bu, döndürme penceresi sırasında eski sertifikayla korunan anahtarların şifresinin çözülmesine olanak tanır.
Bellek içi önbellek ile bellek büyümesi
Belirti
Uygulama bellek tüketimi zaman içinde sürekli olarak artar. Uygulama sabit bellek sınırına sahip bir kapsayıcıda veya App Service planında çalışıyorsa, sonunda yeniden başlatılır veya OutOfMemoryException hatası verir. İzleme, çöp toplama tarafından geri kazanılmadan büyüyen yönetilen yığını gösterir.
Nedeni
Boyut sınırları olmadan kullanmak AddInMemoryTokenCaches() , ilişkisiz önbellek büyümesine neden olur. Bu durum özellikle çok sayıda kullanıcıya hizmet veren uygulamalarda sorunludur çünkü her kullanıcının belirteç girişi belleği süresiz olarak tüketir.
Varsayılan olarak, MemoryCache bir sona erme politikası ayarlanmadığı sürece maksimum boyutu zorlamaz ve girişleri silmez.
Çözüm
A Seçeneği: Boyut sınırı ve kayan süre sonu ayarlama
Bellek içi önbelleği süre sonu ilkeleriyle yapılandırın:
services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(Configuration)
.EnableTokenAcquisitionToCallDownstreamApi()
.AddInMemoryTokenCaches();
services.Configure<MsalMemoryTokenCacheOptions>(options =>
{
options.AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(12);
options.SlidingExpiration = TimeSpan.FromHours(2);
});
Bu ayarlarla, erişimden bağımsız olarak girişlerin süresi 12 saat sonra dolar ve 2 saat boşta kalan girişler daha önce çıkarılır.
B Seçeneği: Dağıtılmış önbelleğe geçme
Çok sayıda eşzamanlı kullanıcısı olan uygulamalar için bellek içi önbellek ölçeklendirilemez. Redis gibi dağıtılmış bir önbelleğe geçin:
services.AddStackExchangeRedisCache(options =>
{
options.Configuration = Configuration.GetConnectionString("Redis");
});
services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(Configuration)
.EnableTokenAcquisitionToCallDownstreamApi()
.AddDistributedTokenCaches();
Dağıtılmış önbellek, uygulama işleminden belleği boşaltır, yeniden başlatmalar arasında belirteçleri kalıcı hale döndürür ve çok örnekli dağıtımları destekler.
C Seçeneği: L1/L2 karma mimarisini kullanma
Microsoft. Identity.Web, hızlı bir bellek içi L1 önbelleğini kalıcı dağıtılmış L2 önbelleğiyle birleştiren karma yaklaşımı destekler. L1/L2 karma önbelleğini yapılandırın:
services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(Configuration)
.EnableTokenAcquisitionToCallDownstreamApi()
.AddDistributedTokenCaches();
services.Configure<MsalDistributedTokenCacheAdapterOptions>(options =>
{
options.L1CacheOptions = new MsalMemoryTokenCacheOptions
{
AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(5),
SlidingExpiration = TimeSpan.FromMinutes(2)
};
});
L1/L2 önbellekleme ile sık erişilen belirteçler, milisaniyenin altında bir gecikme ile bellek içinden (L1) sunulur. L2 önbelleği kalıcılık ve örnekler arası tutarlılık sağlar. L1 önbelleği, bellek büyümesini sınırlamak için kısa süreli süre aşımı kullanır.
Yinelenen MFA veya onay istemleri
Belirti
Son zamanlarda bu adımları tamamlamış olsalar bile kullanıcılardan sürekli olarak çok faktörlü kimlik doğrulaması (MFA) veya onay istenir. Uygulama önbellekte var olan belirteçleri bulamıyor.
Nedeni
Belirteç önbelleği araması geçerli kullanıcı hesabıyla önbelleğe alınmış bir girişle eşleşemediğinde bu sorun oluşur. Yaygın nedenler şunlardır:
- Önbellek anahtarı, belirteç depolandığında kullanılan anahtardan farklıdır. Bu durum
HomeAccountIdveya kiracı bağlamı değiştiğinde oluşabilir. - Uygulama, bellek içi önbelleğe sahip olarak yük dengeleyicinin arkasında birden çok örnek çalıştırır ve istekler, kullanıcının belirtecine sahip olmayan bir örneğe yönlendirilir.
- İstenen talepler veya kapsamlar değiştiğinden önbelleğe alınan belirteç yeni gereksinimi karşılamaz.
- Oturum benzimi etkinleştirilmediğinden, kullanıcılar önbelleğe alınmış belirteçleri olmayan farklı örneklere yönlendirilir.
Tanılama adımları
Belirteçlerin önbellekte neden bulunamadığını belirlemek için şu adımları izleyin:
- Önbellek türünü denetleyin. Çok örnekli bir dağıtımda
AddInMemoryTokenCaches()kullanıyorsanız, bir örnekte önbelleğe alınan belirteçler başka bir örnekte mevcut değildir. Dağıtılmış önbelleğe geçin. - Hesap tanımlayıcısını doğrulayın. Hata ayıklama düzeyi günlüğünü etkinleştirin ve
HomeAccountIdiçin arama yapın. Tanımlayıcının istekler arasında tutarlı olduğunu onaylayın. - Kapsamları inceleyin. tarafından
GetAccessTokenForUserAsyncistenen kapsamların başlangıçta onaylanan kapsamlarla eşleşdiğini onaylayın. Kapsam uyuşmazlığı MSAL'nin yeni bir belirteç istemesine neden olur. - Koşullu Erişim ilkelerini gözden geçirin. Belirli kaynaklar için adım adım kimlik doğrulaması gerektiren Microsoft Entra ID Koşullu Erişim ilkesi, önbelleğe almayla ilgili olmayan ek istemlere neden olur.
Çözüm
1. Adım: Dağıtılmış önbelleğe alma işlemine geçme
Uygulamanız birden çok örnek çalıştırıyorsa, belirteçleri örnekler arasında paylaşmak için dağıtılmış bir önbellek kullanın:
services.AddStackExchangeRedisCache(options =>
{
options.Configuration = Configuration.GetConnectionString("Redis");
});
services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(Configuration)
.EnableTokenAcquisitionToCallDownstreamApi()
.AddDistributedTokenCaches();
2. Adım: Tutarlı kapsamları doğrulama
Belirteçleri (token) alırken talep ettiğiniz kapsamların, kimlik doğrulaması sırasında yapılandırılan kapsamlarla eşleştiğinden emin olun.
// In authentication setup — initial scopes.
.EnableTokenAcquisitionToCallDownstreamApi(new[] { "User.Read", "Mail.Read" })
// When acquiring a token — use the same scopes.
var token = await tokenAcquisition.GetAccessTokenForUserAsync(
new[] { "User.Read", "Mail.Read" });
3. Adım: Oturum bağımlılığını etkinleştirme (geçici çözüm)
Dağıtılmış bir önbelleğe hemen geçemiyorsanız yük dengeleyicinizde oturum bennizimini (yapışkan oturumlar) etkinleştirin. Oturum benzimi, kullanıcının isteklerini aynı örneğe yönlendirir. Bu yaklaşım, ölçeklenebilirlik sınırlamalarıyla geçici bir geçici çözümdür.
Önbellek performansı sorunları
Belirti
Belirteç alma işlemi yavaştır ve aşağı akış API çağrıları gecikme süresini artırır. İzleme, belirteç alma istekleri için ortalama yanıt sürelerinin yüksek olduğunu gösterir. Gecikme süresi kimlik sağlayıcısından değildir; belirteçler önbellekten sunulur.
Nedeni
Önbellek performansı sorunları genellikle aşağıdakilerden kaynaklanır:
- Yüksek L2 önbellek gecikme süresi. Dağıtılmış önbellek yoğun yük altında, uygulamadan coğrafi olarak uzak veya düşük bir hizmet katmanı kullanıyor.
- Büyük belirteç önbellek girdileri. Bir kullanıcı için birçok kaynak için token belirteçlerini önbelleğe alan uygulamalar, okumak ve yazmak için yavaş olan büyük serileştirilmiş önbellek girişleri oluşturabilir.
- L1 önbelleği yok. Her belirteç alımı, sık kullanılan belirteçler için bile ağ üzerinden dağıtılmış önbelleğe gider.
Çözüm
1. Adım: Bellek içi L1 önbelleğini etkinleştirme
L1 önbelleği, sık erişilen belirteçleri işlem belleğinde depolar ve L2'ye ağ gidiş dönüşlerini önler:
services.Configure<MsalDistributedTokenCacheAdapterOptions>(options =>
{
options.L1CacheOptions = new MsalMemoryTokenCacheOptions
{
AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(5),
SlidingExpiration = TimeSpan.FromMinutes(2)
};
});
Bu yapılandırmayla, L1'den sunulan belirteçlerin gecikme süresi milisaniyenin altındadır. L1'de olmayan belirteçler, L2 dağıtılmış önbelleğine geri döner.
2. Adım: Dağıtılmış önbellek katmanını iyileştirme
L2 önbelleği gecikme süresi yüksekse aşağıdaki eylemleri göz önünde bulundurun:
- Redis örneğinin ölçeğini artırma. Daha fazla aktarım hızı ve daha düşük gecikme süresi elde etmek için daha yüksek bir katmana (örneğin, temel katmandan standart veya Redis için Azure Önbellek Premium'a) geçin.
- Coğrafi çoğaltmayı etkinleştirin. Uygulamanız birden çok bölgedeki kullanıcılara hizmet veriyorsa, önbelleğin her bölgenin işlemlerine yakın olması için Redis için Azure Önbellek'in coğrafi çoğaltma özelliğini kullanın.
- Ağ yapılandırmasını gözden geçirin. Uygulama ve önbellek arasındaki ağ atlamalarını azaltmak için Özel Bağlantı veya sanal ağ tümleştirmesini kullanın.
3. Adım: Serileştirilmiş belirteç boyutunu küçültme
Belirteç önbelleği girdileri büyükse, uygulamanın gerekenden daha fazla kaynak için belirteç isteyip istemediğini gözden geçirin. Her benzersiz kaynak ve kapsam bileşimi önbellek girişi boyutuna eklenir. Kullanıcı başına önbelleğe alınan ayrı erişim belirteçlerinin sayısını azaltmak için mümkün olduğunda API çağrılarını birleştirin.
Redis önbellek tahliye
Belirti
Kullanıcılardan, token süresinin dolması temelinde belirli bir düzen olmadan, düzensiz aralıklarla yeniden kimlik doğrulamaları istenir. Redis izleme evicted_keys'nın arttığını ve used_memory'nın maxmemory sınırına yaklaştığını gösteriyor.
Nedeni
Redis sınırına maxmemory ulaştığında, yapılandırılan maxmemory-policy öğesine göre anahtarları siler. Varsayılan ilke (volatile-lru) süresi dolan en son kullanılan anahtarları çıkartır. Redis örneği diğer uygulama verileriyle paylaşılıyorsa, belirteç önbellek girdileri alan için rekabet eder ve erken kaldırılabilir.
Çözüm
1. Adım: Çıkarma ilkesini denetleme
Geçerli çıkarma ilkesini denetleyin:
redis-cli CONFIG GET maxmemory-policy
Belirteç önbellek girdilerinin süre sonu olduğundan dolayı, volatile-lru (varsayılan) belirteç önbellekleri için uygundur. Ancak, süresi dolmamış diğer veriler bellek tüketiyorsa, önce belirteç girişleri çıkarılır.
2. Adım: Ayrılmış redis örneği kullanma
Ayrılmış bir Redis örneği kullanarak belirteç önbelleğini diğer uygulama verilerinden yalıtın:
{
"ConnectionStrings": {
"RedisTokenCache": "token-cache-redis.redis.cache.windows.net:6380,password=...,ssl=True,abortConnect=False",
"RedisAppData": "app-data-redis.redis.cache.windows.net:6380,password=...,ssl=True,abortConnect=False"
}
}
// Register the token cache Redis instance specifically for distributed caching.
services.AddStackExchangeRedisCache(options =>
{
options.Configuration = Configuration.GetConnectionString("RedisTokenCache");
});
3. Adım: Redis bellek sınırını artırma
Özel bir örnek uygun değilse, maxmemory ayarını artırın. Redis için Azure Önbellek'i daha yüksek bir katmana geçin veya önbellek boyutunu artırın.
4. Adım: Uygun önbellek girdisi süre sonu ayarlama
Bellek dolmadan önce eski girdilerin kaldırılması için makul süre sonlarını ayarlayın:
services.Configure<MsalDistributedTokenCacheAdapterOptions>(options =>
{
options.AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(12);
options.SlidingExpiration = TimeSpan.FromHours(2);
});
SQL dağıtılmış önbellek tablosu büyümesi
Belirti
SQL dağıtılmış önbellek tablosu sürekli olarak büyür ve disk alanı tüketir. Önbellek tablosuna karşı veritabanı sorguları zaman içinde yavaştır ve tablo boyutu veya depolama sınırları hakkında uyarılar görebilirsiniz.
Nedeni
SQL Server dağıtılmış önbellek (Microsoft.Extensions.Caching.SqlServer) süresi dolan girdileri otomatik olarak kaldırmaz. Süresi dolan girdiler açıkça temizlenene kadar kalır ve bu da ilişkisiz tablo büyümesine, düşük sorgu performansına ve depolama tüketimine neden olur.
Çözüm
1. Adım: Yinelenen bir temizleme işi ayarlama
Süresi dolan girişleri düzenli aralıklarla kaldırmak için bir SQL Server Agent işi veya zamanlanmış görev oluşturun:
-- Delete expired entries from the SQL distributed cache table.
-- Schedule this query to run every 30 minutes.
DELETE FROM [dbo].[TokenCache]
WHERE ExpiresAtTime < GETUTCDATE();
Tip
Azure SQL Veritabanı'de SQL Server Agent kullanılamadığında, temizleme süreçlerini zamanlamak için Azure Otomasyonu, zamanlayıcı tetikleyiciyle Azure İşlevleri veya Elastic İşler'i kullanın.
2. Adım: Verimli temizleme için dizin ekleme
Önbellek tablosunun son kullanma tarihi sütununda henüz bir dizin yoksa, silme işlemini hızlandırmak için bir dizin ekleyin.
CREATE NONCLUSTERED INDEX IX_TokenCache_ExpiresAtTime
ON [dbo].[TokenCache] (ExpiresAtTime);
3. Adım: Tablo boyutunu izleme
Zaman içinde satır sayısını ve tablo boyutunu izlemek için izleme ekleyin:
SELECT
COUNT(*) AS TotalEntries,
COUNT(CASE WHEN ExpiresAtTime < GETUTCDATE() THEN 1 END) AS ExpiredEntries,
COUNT(CASE WHEN ExpiresAtTime >= GETUTCDATE() THEN 1 END) AS ActiveEntries
FROM [dbo].[TokenCache];
4. Adım: Redis'e geçmeyi göz önünde bulundurun
SQL önbelleği temizlemeyi yönetmek zahmetliyse, yerleşik TTL mekanizması aracılığıyla süre sonunu otomatik olarak işleyen Redis'e geçin:
// Replace SQL distributed cache with Redis.
services.AddStackExchangeRedisCache(options =>
{
options.Configuration = Configuration.GetConnectionString("Redis");
});
Genel sorun giderme ipuçları
Sorununuz bu makaledeki belirli bir senaryoyla eşleşmediğinde bu ipuçlarını kullanın.
Önbelleğin kullanıldığını doğrulama
Belirteçlerin önbellekten okunup önbelleğe yazıldığını doğrulamak için geçici kayıt ekleyin.
services.Configure<MsalDistributedTokenCacheAdapterOptions>(options =>
{
options.Encrypt = false; // Disable encryption temporarily for debugging only.
options.OnL2CacheFailure = (ex) =>
{
logger.LogError(ex, "L2 cache operation failed.");
return true;
};
});
Birden çok önbellek kaydını denetleme
Başlangıç kodunuzda birden çok çağrı AddInMemoryTokenCaches() veya AddDistributedTokenCaches() mevcutsa, son kaydı öncelik kazanır. Yalnızca bir önbellek türünün kayıtlı olduğunu doğrulayın.
Belirteç ömrünü gözden geçirme
Erişim belirteçlerinin süresi sınırlıdır (genellikle 60-90 dakika). Kullanıcılar bu süreden sonra yeniden kimlik doğrulama raporu verirse, önbellek sorunu yerine davranış beklenir. Yenileme belirteçleri yeni erişim belirteçlerini sessizce alır ve önbellekte depolanır. Yenileme belirteci eksikse veya süresi dolmuşsa, kullanıcının yeniden kimlik doğrulaması yapması gerekir.
Temiz bir önbellekle test edin
Sorunları tanılarken, bozuk veya eski girdileri eleyerek önbelleği temizleyin:
- Bellek içi önbellek: Uygulamayı yeniden başlatın.
-
Redis: Önbellek veritabanında komutunu çalıştırın
FLUSHDB. - SQL Server: Önbellek tablosundaki tüm satırları silin.
Uygulama yeniden başlatıldıktan sonra belirteç önbelleği boş
Belirti
Her uygulama yeniden başlatıldıktan veya yeniden dağıtıldıktan sonra kullanıcıların yeniden kimlik doğrulaması yapması gerekir. Dağıtılmış önbellek boş görünüyor veya belirteçler kalıcı değil.
Nedeni
Bu sorun genellikle üretimde bir bellek içi önbellek (AddInMemoryTokenCaches()) veya kalıcı olmayan dağıtılmış bellek önbelleği (AddDistributedMemoryCache()) kullandığınızda oluşur. Her iki seçenek de uygulamanın yeniden başlatılmasında belirteçleri kalıcı hale getirmez.
AddDistributedMemoryCache() verileri belleğe depolayan bir IDistributedCache uygulama kaydeder. "Dağıtılmış" adına rağmen, verileri harici olarak depolamaz ve yalnızca geliştirme ve test için tasarlanmıştır.
Çözüm
Kalıcı bir dağıtılmış önbelleğe geçin:
// Register a persistent cache (Redis example).
builder.Services.AddStackExchangeRedisCache(options =>
{
options.Configuration = builder.Configuration.GetConnectionString("Redis");
options.InstanceName = "MyApp_";
});
// Use distributed token caches instead of in-memory.
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(builder.Configuration)
.EnableTokenAcquisitionToCallDownstreamApi()
.AddDistributedTokenCaches();
Uyarı
Kalıcı bir dağıtılmış önbellekle karıştırmayın AddDistributedMemoryCache() . Üretim iş yükleri için AddStackExchangeRedisCache() (Redis), AddDistributedSqlServerCache() (SQL Server) veya başka bir kalıcı IDistributedCache uygulaması kullanın.