Web Performansı & HTTP Önbellekleme 4 dk okuma 24 okunma

Response Caching ve ETag Kullanımı

Response Caching, HTTP yanıtlarını istemci veya sunucu tarafında önbellekleyerek tekrarlı isteklerin maliyetini düşürür. ETag ise kaynağın sürüm kimliğidir; If-None-Match ile koşullu istek yapılarak değişmeyen içerik için 304 Not Modified dönülür ve gövde tekrar gönderilmez. .NET'te Response Caching Middleware ve Output Cache ile yapılandırılır; ETag yeniden doğrulama ile bant genişliği tasarrufu sağlanır.

Response Caching ve ETag Kullanımı

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 OK döner.

  • Eşleşiyorsa (kaynak değişmemiş): 304 Not Modified dö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:

  • Authorization başlığı içeren isteklerin yanıtları önbelleğe alınmaz .

  • VaryByQueryKeys yalnı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.

Tüm yazılar Soru ya da yorumun mu var? Yaz