Response Caching ve ETag Kullanımı
Web API'lerinde performansın en görünmez ama en etkili araçlarından biri, HTTP önbellekleme mekanizmalarıdır. Response Caching, bir yanıtın önbelleğe alınmasını ve tekrar kullanılmasını sağlarken; ETag, önbelleğe alınmış bir yanıtın hâlâ geçerli olup olmadığını doğrulamanın standart yolunu sunar. İkisi birlikte kullanıldığında, hem sunucu yükü hem de ağ trafiği önemli ölçüde azalır.
1. Response Caching Nedir?
Response Caching, bir HTTP yanıtının (genellikle GET veya HEAD isteklerine ait) istemci, proxy veya sunucu tarafından saklanması ve aynı kaynağa yapılan sonraki isteklerde yeniden kullanılmasıdır . Bu mekanizma, yanıtı yeniden üretmek için gereken CPU ve veritabanı işini ortadan kaldırır.
Temel Cache-Control Direktifleri:
| Direktif | Anlamı |
|---|---|
public |
Yanıt, paylaşılan önbelleklerde (proxy, CDN) saklanabilir. |
private |
Yanıt yalnızca istemcinin kendi önbelleğinde saklanabilir. |
max-age |
Yanıtın kaç saniye boyunca taze sayılacağı. |
no-cache |
Yanıt saklanabilir, ancak her kullanımdan önce sunucuda doğrulanmalıdır. |
no-store |
Yanıt hiçbir yerde saklanmamalıdır (hassas veriler için). |
Dikkat: ASP.NET Core Response Caching Middleware yalnızca 200 OK durum kodlu yanıtları önbelleğe alır; hata sayfaları ve diğer durum kodları önbelleğe alınmaz .
2. ETag Nedir ve Neden Gereklidir?
ETag (Entity Tag), bir kaynağın belirli bir sürümünü tanımlayan benzersiz bir dizedir. Sunucu, yanıtla birlikte bir ETag başlığı gönderir. İstemci aynı kaynağı tekrar talep ettiğinde, elindeki ETag değerini If-None-Match başlığında gönderir. Sunucu, kaynağın mevcut ETag'i ile karşılaştırır:
-
Eşleşmiyorsa (kaynak değişmiş): Yeni içerikle birlikte
200 OKdöner. -
Eşleşiyorsa (kaynak değişmemiş):
304 Not Modifieddöner ve gövde gönderilmez .
Kazanç: İstemci, değişmeyen bir kaynağın tam gövdesini tekrar indirmez; yalnızca küçük bir başlık trafiği oluşur. Bu, özellikle büyük yanıtlarda bant genişliği tasarrufu sağlar.
Güçlü vs. Zayıf ETag:
-
Güçlü ETag: Kaynağın byte düzeyinde aynı olduğunu garanti eder (
"abc123"). -
Zayıf ETag: Anlamsal olarak aynı olduğunu belirtir (
W/"abc123"); byte düzeyinde farklılık olabilir.
3. .NET'te Response Caching Middleware
ASP.NET Core, HTTP önbellekleme semantiğini uygulayan bir Response Caching Middleware sunar.
Kurulum:
csharp
// Program.cs builder.Services.AddResponseCaching(); var app = builder.Build(); // Sıralama önemli: UseCors, UseResponseCaching'den önce çağrılmalı app.UseCors(); app.UseResponseCaching();
Controller'da [ResponseCache] Kullanımı:
csharp
[HttpGet("{id}")]
[ResponseCache(Duration = 60, Location = ResponseCacheLocation.Any, VaryByQueryKeys = new[] { "id" })]
public IActionResult GetProduct(int id)
{
return Ok(_productService.Get(id));
}
Duration = 60, yanıtın 60 saniye boyunca Cache-Control: public, max-age=60 ile önbelleğe alınmasını sağlar . Location.Any (public) paylaşılan önbelleklere, Location.Client (private) ise yalnızca istemci önbelleğine izin verir.
Önemli Kısıtlar:
-
Authorizationbaşlığı içeren isteklerin yanıtları önbelleğe alınmaz . -
VaryByQueryKeysyalnızca middleware etkinleştirildiğinde çalışır; aksi halde runtime hatası alınır .
4. Output Caching: Daha Esnek Alternatif (.NET 7+)
Response Caching Middleware, HTTP semantiğine sıkı sıkıya bağlıdır ve yalnızca public yanıtları önbelleğe alır. Output Caching ise daha esnektir: HTTP başlıklarından bağımsız olarak, yapılandırma ile neyin önbelleğe alınacağını belirler .
Temel Kullanım:
csharp
builder.Services.AddOutputCache(options =>
{
options.AddBasePolicy(builder => builder.Expire(TimeSpan.FromSeconds(10)));
options.AddPolicy("Query", builder => builder.SetVaryByQuery("culture"));
});
var app = builder.Build();
app.UseOutputCache();
app.MapGet("/products", GetProducts).CacheOutput();
ETag ile Yeniden Doğrulama (Output Cache):
Output Cache, istemciden gelen If-None-Match başlığını otomatik olarak işler. Yanıtla birlikte bir ETag gönderirseniz, istemci aynı ETag ile tekrar geldiğinde 304 Not Modified döner .
csharp
app.MapGet("/etag", async (HttpContext context) =>
{
var etag = $"\"{Guid.NewGuid():n}\""; // Gerçekte içerik hash'i kullanın
context.Response.Headers.ETag = etag;
await context.Response.WriteAsync("İçerik");
}).CacheOutput();
5. ETag Üretimi: Ne Kullanmalı?
ETag, kaynağın içeriğinden türetilmelidir. Yaygın yaklaşımlar:
| Yöntem | Açıklama | Uygunluk |
|---|---|---|
| İçerik Hash'i (MD5/SHA) | Yanıt gövdesinin hash'i | ✅ Doğru; içerik değişince ETag değişir |
| Veritabanı Zaman Damgası | LastModified alanı |
✅ İyi; ancak aynı saniyedeki değişiklikleri kaçırabilir |
| Sürüm Numarası | Kaynağın versiyon alanı | ✅ İdeal; açık ve deterministik |
| Rastgele GUID | Her yanıtta yeni | ❌ Yanlış; önbellekleme anlamsızlaşır |
En İyi Pratik: ETag'i, yanıt gövdesinin hash'inden veya kaynağın sürüm numarasından üretin. Rastgele değerler, her istekte "değişmiş" gibi görünmesine ve önbelleklemenin hiç işe yaramamasına yol açar.
6. Ne Zaman Hangisi?
| Senaryo | Öneri |
|---|---|
| Herkese açık, sık okunan veriler (ürün listesi, kategori) | public + max-age + ETag |
| Kullanıcıya özel veriler (profil, siparişler) | private + no-store veya kısa max-age |
| Değişmeyen statik içerik | Uzun max-age + içerik hash'li ETag |
| Sık değişen ama doğrulanabilir içerik | no-cache + ETag (her istekte 304 kontrolü) |
| Hassas veriler (token, ödeme bilgisi) | no-store (asla önbelleğe alınmaz) |
7. En İyi Pratikler
| Pratik | Açıklama |
|---|---|
| ETag'i deterministik üretin | İçerik hash'i veya sürüm numarası; rastgele GUID değil. |
304 yanıtlarında gövde göndermeyin |
304 Not Modified yanıtı gövdesiz olmalıdır . |
Authorization içeren yanıtları önbelleğe almayın |
Middleware bunu otomatik yapar, ancak no-store ile açıkça belirtin . |
Vary başlığını doğru kullanın |
Vary: Accept-Encoding ile sıkıştırma varyantlarını ayırın. |
| Önbellek boyutunu sınırlayın | SizeLimit ve MaximumBodySize ile bellek kullanımını kontrol edin . |
Sonuç
Response Caching ve ETag, HTTP'nin sunduğu en olgun performans araçlarıdır. Response Caching, yanıtları önbellekleyerek sunucu yükünü azaltır; ETag ise koşullu isteklerle değişmeyen içeriğin tekrar indirilmesini engeller. .NET'te Response Caching Middleware ve Output Cache ile bu mekanizmalar kolayca uygulanır. Unutmayın: Önbellekleme, doğru yapılandırıldığında görünmez bir hızlandırıcıdır; yanlış yapılandırıldığında ise güncel olmayan veri ve güvenlik açığı kaynağıdır.