Merhaba arkadaşlar, bugün başımı çok ağrıtan bir konudan, özellikle de statik asset'lerin ve API yanıtlarının cache'lenmesinden bahsedeceğim. Projemde CDN ve tarayıcı cache'ini yönetirken, Last-Modified header'ını kullanıyordum ve işler yolunda gidiyor gibiydi. Ta ki, bir dosyanın içeriği değiştiği halde zaman damgasının aynı kaldığı (saniye bazında) bir senaryoya kadar! İşte o an kafayı yemiştim. Neyse ki, ETag (Entity Tag) kavramı imdadıma yetişti ve bugün size neden dosya içeriği değişikliklerinde ETag'ın daha üstün olduğunu anlatacağım.
Karşılaştığım Sorun: Last-Modified'in Zaman Tuzağı
Bir deployment sırasında, bir CSS dosyasında küçük bir düzeltme yaptım. Dosya, sunucuda aynı saniye içinde "touch" edildiği veya overwrite edildiği için, Last-Modified değeri değişmedi. Sonuç? Kullanıcıların tarayıcıları "304 Not Modified" alıp, eski, hatalı CSS dosyasını cache'inden servis etmeye devam etti. Bu, cache invalidation'ın en klasik ve can sıkıcı problemlerinden biri. Last-Modified, sadece zaman damgasına bakar, içeriğin gerçekten değişip değişmediğini bilmez.
ETag'ın Dahice Çözümü: İçeriğin Parmak İzi
ETag ise bu işi dosyanın veya içeriğin bir nevi "hash"ini (parmak izini) alarak çözüyor. Sunucu, yanıtla birlikte bu hash değerini bir header olarak gönderiyor. İstemci (tarayıcı) bir sonraki isteğinde, cache'inde sakladığı bu ETag değerini If-None-Match header'ı ile sunucuya gönderiyor. Sunucu, mevcut dosyanın hash'ini tekrar hesaplayıp, gelen ETag ile karşılaştırıyor. Hash'ler uyuşmuyorsa, içerik değişmiş demektir ve sunucu taze dosyayı (200 OK) iletiyor.
İşte basit bir Node.js (Express) örneği:
Neden Daha Üstün? Avantajlar Listesi
1. İçerik Bazlı Doğruluk: En büyük avantajı bu. Dosya aynı saniyede 10 kere değişse, her seferinde farklı bir ETag üretilir. Cache, kesinlikle doğru şekilde invalidate olur.
2. Zaman Senkronizasyonu Sorunu Yok: Last-Modified, sunucu ve istemci saatlerinin senkronize olmasını gerektirir. ETag'ta böyle bir bağımlılık yok.
3. Dinamik İçerikler için Elverişli: Bir API endpoint'inin döndürdüğü JSON verisi için ETag üretmek, Last-Modified zamanı belirlemekten çok daha kolay ve mantıklı.
4. Granüler Kontrol: ETag'ı sadece dosyanın tamamı için değil, önemli bir kısmı değiştiğinde invalidate etmek için de özelleştirebilirsiniz (weak ETag vs strong ETag).
Tabii ki, ETag'ın da küçük bir maliyeti var. Her istekte hash hesaplama işlemi CPU kullanır. Büyük dosyalar veya çok yüksek trafikli endpoint'ler için weak ETag kullanmayı veya hash'i önceden hesaplayıp saklamayı düşünebilirsiniz.
Sonuç olarak, eğer cache invalidation konusunda "kesin" ve "güvenilir" bir çözüm istiyorsanız, özellikle içeriğin sık ve hızlı güncellendiği durumlarda, Last-Modified'e göre ETag kullanmanızı şiddetle tavsiye ederim. Ben bu geçişi yaptıktan sonra "cache temizleme" panikleri tarih oldu.
Peki ya siz? API veya asset cache'leme stratejinizde hangi yöntemi kullanıyorsunuz? Hiç Last-Modified yüzünden benzer bir sorun yaşadınız mı? Weak ETag vs Strong ETag konusunda deneyimleriniz neler? Yorumlarda buluşalım!
Bir deployment sırasında, bir CSS dosyasında küçük bir düzeltme yaptım. Dosya, sunucuda aynı saniye içinde "touch" edildiği veya overwrite edildiği için, Last-Modified değeri değişmedi. Sonuç? Kullanıcıların tarayıcıları "304 Not Modified" alıp, eski, hatalı CSS dosyasını cache'inden servis etmeye devam etti. Bu, cache invalidation'ın en klasik ve can sıkıcı problemlerinden biri. Last-Modified, sadece zaman damgasına bakar, içeriğin gerçekten değişip değişmediğini bilmez.
ETag ise bu işi dosyanın veya içeriğin bir nevi "hash"ini (parmak izini) alarak çözüyor. Sunucu, yanıtla birlikte bu hash değerini bir header olarak gönderiyor. İstemci (tarayıcı) bir sonraki isteğinde, cache'inde sakladığı bu ETag değerini If-None-Match header'ı ile sunucuya gönderiyor. Sunucu, mevcut dosyanın hash'ini tekrar hesaplayıp, gelen ETag ile karşılaştırıyor. Hash'ler uyuşmuyorsa, içerik değişmiş demektir ve sunucu taze dosyayı (200 OK) iletiyor.
İşte basit bir Node.js (Express) örneği:
JavaScript:
const express = require('express');
const crypto = require('crypto');
const fs = require('fs').promises;
const app = express();
app.get('/api/config', async (req, res) => {
try {
const data = await fs.readFile('./config.json', 'utf8');
// İçeriğin MD5 hash'ini ETag olarak oluştur
const etag = crypto.createHash('md5').update(data).digest('hex');
// İstemcinin gönderdiği ETag'ı al
const clientEtag = req.headers['if-none-match'];
// ETag'lar eşleşirse, 304 döndür
if (clientEtag && clientEtag === etag) {
return res.status(304).end();
}
// Eşleşmezse, yeni ETag header'ını set et ve datayı gönder
res.set('ETag', etag);
res.json(JSON.parse(data));
} catch (error) {
res.status(500).send('Dosya okunamadı');
}
});
app.listen(3000, () => console.log('Sunucu 3000 portunda...'));
1. İçerik Bazlı Doğruluk: En büyük avantajı bu. Dosya aynı saniyede 10 kere değişse, her seferinde farklı bir ETag üretilir. Cache, kesinlikle doğru şekilde invalidate olur.
2. Zaman Senkronizasyonu Sorunu Yok: Last-Modified, sunucu ve istemci saatlerinin senkronize olmasını gerektirir. ETag'ta böyle bir bağımlılık yok.
3. Dinamik İçerikler için Elverişli: Bir API endpoint'inin döndürdüğü JSON verisi için ETag üretmek, Last-Modified zamanı belirlemekten çok daha kolay ve mantıklı.
4. Granüler Kontrol: ETag'ı sadece dosyanın tamamı için değil, önemli bir kısmı değiştiğinde invalidate etmek için de özelleştirebilirsiniz (weak ETag vs strong ETag).
Tabii ki, ETag'ın da küçük bir maliyeti var. Her istekte hash hesaplama işlemi CPU kullanır. Büyük dosyalar veya çok yüksek trafikli endpoint'ler için weak ETag kullanmayı veya hash'i önceden hesaplayıp saklamayı düşünebilirsiniz.
Sonuç olarak, eğer cache invalidation konusunda "kesin" ve "güvenilir" bir çözüm istiyorsanız, özellikle içeriğin sık ve hızlı güncellendiği durumlarda, Last-Modified'e göre ETag kullanmanızı şiddetle tavsiye ederim. Ben bu geçişi yaptıktan sonra "cache temizleme" panikleri tarih oldu.
Peki ya siz? API veya asset cache'leme stratejinizde hangi yöntemi kullanıyorsunuz? Hiç Last-Modified yüzünden benzer bir sorun yaşadınız mı? Weak ETag vs Strong ETag konusunda deneyimleriniz neler? Yorumlarda buluşalım!