Vary Başlığını Anlamak
Yayınlanan: 2022-03-10Vary HTTP başlığı, her gün milyarlarca HTTP yanıtı olarak gönderilir. Ancak kullanımı hiçbir zaman orijinal vizyonunu yerine getirmedi ve birçok geliştirici ne yaptığını yanlış anlıyor veya web sunucularının onu gönderdiğinin farkında bile değil. İstemci İpuçları, Varyantlar ve Anahtar özelliklerin gelmesiyle birlikte, çeşitli yanıtlar yeni bir başlangıç yapıyor.
Vary nedir?
Vary'nin hikayesi, web'in nasıl çalışması gerektiğine dair güzel bir fikirle başlar. Prensipte, bir URL bir web sayfasını değil, banka ekstreniz gibi kavramsal bir kaynağı temsil eder. Banka ekstrenizi görmek istediğinizi düşünün: bank.com
ve /statement
için bir GET
isteği gönderiyorsunuz. Buraya kadar çok iyi, ancak ifadenin hangi formatta olmasını istediğinizi söylemediniz. Bu nedenle tarayıcınız isteğinize Accept: text/html
gibi bir şey de ekleyecektir. Teoride, en azından bu, bunun yerine Accept: text/csv
diyebileceğiniz ve aynı kaynağı farklı bir biçimde alabileceğiniz anlamına gelir.

Aynı URL artık Accept
başlığının değerine bağlı olarak farklı yanıtlar ürettiğinden, bu yanıtı depolayan tüm önbelleklerin bu başlığın önemli olduğunu bilmesi gerekir. Sunucu bize Accept
başlığının şu şekilde önemli olduğunu söyler:
Vary: Accept
Bunu, "Bu yanıt, isteğinizin Accept
başlığının değerine göre değişir" şeklinde okuyabilirsiniz.
Bu temelde bugünün web'inde çalışmıyor . Sözde "içerik pazarlığı" harika bir fikirdi, ancak başarısız oldu. Bu, Vary
işe yaramaz olduğu anlamına gelmez. Web'de ziyaret ettiğiniz sayfaların iyi bir kısmı yanıtta bir Vary
başlığı taşır - belki web sitelerinizde de vardır ve bunu bilmiyorsunuzdur. Öyleyse, başlık içerik anlaşması için çalışmıyorsa, neden hala bu kadar popüler ve tarayıcılar bununla nasıl başa çıkıyor? Hadi bir bakalım.
Vary hakkında daha önce içerik dağıtım ağları (CDN'ler), sunucularınız ve kullanıcı arasına koyabileceğiniz aracı önbellekler (Fastly, CloudFront ve Akamai gibi) ile ilgili olarak yazmıştım. Tarayıcıların ayrıca Vary kurallarını anlaması ve bunlara yanıt vermesi gerekir ve bunu yapma biçimleri, Vary'e CDN'ler tarafından davranılma biçiminden farklıdır. Bu yazıda, tarayıcıdaki önbellek varyasyonunun karanlık dünyasını keşfedeceğim.
Tarayıcıda Değişen Bugünün Kullanım Durumları
Daha önce gördüğümüz gibi, Vary'nin geleneksel kullanımı, Accept
, Accept-Language
ve Accept-Encoding
başlıklarını kullanarak içerik anlaşması yapmaktır ve tarihsel olarak, bunlardan ilk ikisi sefil bir şekilde başarısız olmuştur. Desteklenen yerlerde Gzip veya Brotli ile sıkıştırılmış yanıtlar sunmak için Accept-Encoding
göre değişiklik yapmak, çoğunlukla oldukça iyi çalışır, ancak bugünlerde tüm tarayıcılar Gzip'i desteklemektedir, bu nedenle bu çok heyecan verici değildir.
Bu senaryolardan bazılarına ne dersiniz?
- Kullanıcı ekranının tam genişliği olan görüntüler sunmak istiyoruz. Kullanıcı tarayıcısını yeniden boyutlandırırsa, yeni görüntüler indiririz (İstemci İpuçlarına göre değişir).
- Kullanıcı oturumu kapatırsa, oturum açtıkları sırada önbelleğe alınan sayfaları kullanmaktan kaçınmak isteriz (
Key
olarak bir tanımlama bilgisi kullanarak). - WebP görüntü biçimini destekleyen tarayıcıların kullanıcıları WebP görüntüleri almalıdır; aksi takdirde, JPEG'leri almaları gerekir.
- Yüksek yoğunluklu bir ekranda bir tarayıcı kullanırken, kullanıcı 2x görüntü almalıdır. Tarayıcı penceresini standart yoğunluklu bir ekrana taşırlar ve yenilerlerse 1x görüntü almaları gerekir.
Tamamen Aşağı Önbellekler
Tüm kullanıcılar tarafından paylaşılan devasa bir önbellek görevi gören uç önbelleklerin aksine, tarayıcı yalnızca tek bir kullanıcı içindir, ancak farklı, özel kullanımlar için birçok farklı önbelleğe sahiptir:

Bunlardan bazıları oldukça yenidir ve içeriğin tam olarak hangi önbellekten yüklendiğini anlamak, geliştirici araçları tarafından yeterince desteklenmeyen karmaşık bir hesaplamadır. İşte bu önbelleklerin yaptıkları:
- görüntü önbelleği
Bu, kodu çözülmüş görüntü verilerini depolayan, sayfa kapsamlı bir önbellektir; bu nedenle, örneğin, aynı görüntüyü bir sayfaya birden çok kez eklerseniz, tarayıcının yalnızca bir kez indirmesi ve kodunu çözmesi gerekir. - ön yükleme önbelleği
Bu aynı zamanda sayfa kapsamlıdır ve kaynak normalde önbelleğe alınamaz olsa bile birLink
başlığında veya bir<link rel="preload">
etiketinde önceden yüklenmiş olan her şeyi depolar. Görüntü önbelleği gibi, kullanıcı sayfadan ayrıldığında ön yükleme önbelleği de yok edilir. - hizmet çalışanı önbellek API'si
Bu, programlanabilir bir arayüze sahip bir önbellek arka ucu sağlar; bu nedenle, bir servis çalışanına JavaScript kodu aracılığıyla özellikle koymadığınız sürece hiçbir şey burada saklanmaz. Ayrıca, yalnızca bunu bir hizmet çalışanıfetch
işleyicisinde açıkça yaparsanız kontrol edilir. Hizmet çalışanı önbelleği, kaynak kapsamlıdır ve kalıcı olması garanti edilmese de, tarayıcının HTTP önbelleğinden daha kalıcıdır. - HTTP önbelleği
Bu, insanların en aşina olduğu ana önbellektir.Cache-Control
gibi HTTP düzeyindeki önbellek başlıklarına dikkat eden tek önbellektir ve bir şeyin önbelleğe alınıp alınmayacağını ve ne kadar süreyle önbelleğe alınacağını belirlemek için bunları tarayıcının kendi buluşsal kurallarıyla birleştirir. Tüm web siteleri tarafından paylaşılan en geniş kapsama sahiptir; bu nedenle, alakasız iki web sitesi aynı varlığı (örneğin, Google Analytics) yüklerse, aynı önbellek isabetini paylaşabilirler. - HTTP/2 push önbelleği (veya “H2 push önbelleği”)
Bu, bağlantıyla birlikte oturur ve sunucudan gönderilen ancak bağlantıyı kullanan herhangi bir sayfa tarafından henüz talep edilmeyen nesneleri depolar. Belirli bir bağlantı kullanan sayfalara kapsamlandırılır; bu, temelde tek bir Köken kapsamına alınmakla aynıdır, ancak bağlantı kapandığında da yok edilir.
Bunlardan HTTP önbelleği ve hizmet çalışanı önbelleği en iyi şekilde tanımlanır. Görüntü ve ön yükleme önbelleklerine gelince, bazı tarayıcılar bunları belirli bir navigasyonun oluşturulmasına bağlı tek bir “bellek önbelleği” olarak uygulayabilir, ancak burada tarif ettiğim zihinsel model, süreç hakkında düşünmek için hala doğru yoldur. İlgileniyorsanız, preload
ilgili teknik özellik notuna bakın. H2 server push durumunda, bu önbelleğin akıbeti üzerine tartışma aktif kalır.
Bir isteğin ağa çıkmadan önce bu önbellekleri kontrol ettiği sıra önemlidir, çünkü bir şey talep etmek onu dış önbellek katmanından bir iç katmana çekebilir. Örneğin, HTTP/2 sunucunuz buna ihtiyaç duyan bir sayfayla birlikte bir stil sayfası gönderirse ve bu sayfa ayrıca stil sayfasını bir <link rel="preload">
etiketiyle önceden yüklerse, stil sayfası üçe dokunur. tarayıcıda önbellekler. İlk olarak, talep edilmeyi bekleyen H2 push önbelleğinde oturacaktır. Tarayıcı sayfayı oluştururken ve preload
etiketine ulaştığında, stil sayfasını HTTP önbelleği (biçim sayfasının Cache-Control
başlığına bağlı olarak saklayabilir) aracılığıyla push önbelleğinden çeker ve kaydeder önyükleme önbelleğinde.

Vary As A Validator ile Tanışın
Tamam peki bu durumu alıp Vary'yi karışıma eklediğimizde ne oluyor?
Aracı önbelleklerin (örneğin CDN'ler) aksine, tarayıcılar genellikle URL başına birden çok varyasyon depolama yeteneğini uygulamaz . Bunun mantığı, genellikle Vary
için kullandığımız şeylerin (özellikle Accept-Encoding
ve Accept-Language
) tek bir kullanıcı bağlamında sık sık değişmemesidir. Accept-Encoding
bir tarayıcı yükseltmesiyle değişebilir (ancak muhtemelen değişmez) ve Accept-Language
büyük olasılıkla yalnızca işletim sisteminizin dil yerel ayarlarını düzenlerseniz değişir. Bazı belirtim yazarları bunun bir hata olduğuna inansa da, Vary'yi bu şekilde uygulamak çok daha kolay olur.
Bir tarayıcının yalnızca bir varyasyonu saklaması çoğu zaman büyük bir kayıp değildir, ancak "değişkenlik" verileri değişirse artık geçerli olmayan bir varyasyonu yanlışlıkla kullanmamamız önemlidir.
Uzlaşma, Vary
bir anahtar değil, bir doğrulayıcı olarak davranmaktır. Tarayıcılar, önbellek anahtarlarını normal şekilde (esas olarak URL'yi kullanarak) hesaplar ve ardından bir isabet alırlarsa, isteğin önbelleğe alınan yanıtta oluşturulan Vary kurallarını karşılayıp karşılamadığını kontrol ederler. Olmazsa, tarayıcı isteği önbellekte bir kayıp olarak değerlendirir ve bir sonraki önbellek katmanına veya ağın dışına geçer. Yeni bir yanıt alındığında, teknik olarak farklı bir varyasyon olsa bile önbelleğe alınmış sürümün üzerine yazacaktır.
Değişken Davranış Gösterme
Vary
nasıl işlendiğini göstermek için küçük bir test takımı hazırladım. Test, farklı başlıklara göre değişen bir dizi farklı URL yükler ve isteğin önbelleğe ulaşıp ulaşmadığını tespit eder. Başlangıçta bunun için ResourceTiming kullanıyordum, ancak daha fazla uyumluluk için, yalnızca isteğin tamamlanmasının ne kadar sürdüğünü ölçmeye geçtim (ve farkı gerçekten netleştirmek için kasıtlı olarak sunucu tarafı yanıtlarına 1 saniyelik bir gecikme ekledim).

Önbellek türlerinin her birine ve Vary
nasıl çalışması gerektiğine ve gerçekte böyle çalışıp çalışmadığına bakalım. Her test için, burada önbellekten bir sonuç görmeyi bekleyip beklemeyeceğimizi ("HIT" veya "MISS") ve gerçekte ne olduğunu gösteriyorum.
ön yükleme
Ön yükleme şu anda yalnızca, önceden yüklenmiş yanıtların sayfa tarafından ihtiyaç duyulana kadar bir bellek önbelleğinde saklandığı Chrome'da desteklenmektedir. Yanıtlar, HTTP önbelleğe alınabilirlerse, ön yükleme önbelleğine giderken HTTP önbelleğini de doldurur. Ön yüklemeli istek başlıklarını belirtmek imkansız olduğundan ve ön yükleme önbelleği yalnızca sayfa boyunca sürdüğünden, bunu test etmek zordur, ancak en azından Vary
başlığına sahip nesnelerin başarıyla önceden yüklendiğini görebiliriz:

Hizmet Çalışanı Önbelleği API'si
Chrome ve Firefox servis çalışanlarını destekliyor ve servis çalışanı spesifikasyonunu geliştirirken, yazarlar tarayıcılarda bozuk uygulamalar olarak gördüklerini düzeltmek, tarayıcıda Vary
daha çok CDN'ler gibi çalışmasını sağlamak istediler. Bu, tarayıcının HTTP önbelleğinde yalnızca bir varyasyon saklaması gerekirken, Önbellek API'sinde birden çok varyasyonu tutması gerektiği anlamına gelir. Firefox (54) bunu doğru bir şekilde yaparken Chrome, HTTP önbelleği için kullandığı doğrulayıcı olarak değiştir mantığının aynısını kullanır (hata izlenir).

HTTP Önbelleği
Ana HTTP önbelleği, Vary
gözlemlemeli ve bunu tüm tarayıcılarda tutarlı bir şekilde (doğrulayıcı olarak) yapmalıdır. Bununla ilgili çok daha fazlası için Mark Nottingham'ın “Tarayıcı Önbelleğe Alma Durumu, Yeniden Ziyaret Edildi” yazısına bakın.
HTTP/2 Önbelleği İletme
Vary
gözlemlenmelidir, ancak pratikte hiçbir tarayıcı buna gerçekten saygı göstermez ve tarayıcılar, yanıtların değiştiği başlıklarda rastgele değerler taşıyan isteklerle gönderilen yanıtları mutlu bir şekilde eşleştirir ve tüketir.

“304 (Değiştirilmemiş)” Kırışıklığı
HTTP "304 (Değiştirilmedi)" yanıt durumu büyüleyici. "Sevgili liderimiz" Artur Bergman, HTTP önbelleğe alma spesifikasyonunda bana bu cevheri işaret etti (benimki vurgulandı):
304 yanıtı oluşturan sunucu , aynı isteğe 200 (Tamam) yanıt olarak gönderilecek olan aşağıdaki başlık alanlarından herhangi birini oluşturmalıdır:
Cache-Control
,Content-Location
,Date
,ETag
,Expires
veVary
.
Bir 304
yanıtı neden bir Vary
başlığı döndürür? Bu başlıkları içeren bir 304
yanıtı aldığınızda ne yapmanız gerektiğini okuduğunuzda arsa kalınlaşır:
Güncelleme için saklanan bir yanıt seçilirse, önbellek , depolanan yanıttaki karşılık gelen başlık alanlarının tüm örneklerini değiştirmek için 304 (Değiştirilmemiş) yanıtında sağlanan diğer başlık alanlarını \[…] kullanmalıdır.
Bir dakika ne? Öyleyse, 304
Vary
başlığı mevcut önbelleğe alınmış nesnedekinden farklıysa, önbelleğe alınmış nesneyi güncellememiz gerekiyor mu? Ancak bu, artık yaptığımız istekle eşleşmediği anlamına gelebilir!
Bu senaryoda, ilk bakışta, 304
size aynı anda önbelleğe alınmış sürümü kullanabileceğinizi ve kullanamayacağınızı söylüyor gibi görünüyor. Elbette, sunucu önbelleğe alınmış sürümü kullanmanızı gerçekten istemeseydi, 304
değil 200
gönderirdi; bu nedenle, önbelleğe alınmış sürüm kesinlikle kullanılmalıdır - ancak güncellemeleri bu sürüme uyguladıktan sonra, ilk başta önbelleği dolduranla aynı olan gelecekteki bir istek için tekrar kullanılmayabilir.
(Yan not: Fastly'de, spesifikasyonun bu tuhaflığına saygı duymuyoruz. Dolayısıyla, kaynak sunucunuzdan bir 304
alırsak, TTL'yi sıfırlamak dışında önbelleğe alınmış nesneyi değiştirilmemiş olarak kullanmaya devam edeceğiz.)
Tarayıcılar buna saygı duyuyor gibi görünüyor, ancak bir tuhaflık var. Güncellemeden sonra önbelleğe alınan yanıtın mevcut istekle eşleşmesini sağlamak için yalnızca yanıt başlıklarını değil, bunlarla eşleşen istek başlıklarını da güncellerler. Bu mantıklı görünüyor. Spesifikasyon bundan bahsetmiyor, bu nedenle tarayıcı satıcıları istediklerini yapmakta özgürler; Neyse ki, tüm tarayıcılar aynı davranışı sergiler.
Müşteri İpuçları
Google'ın İstemci İpuçları özelliği, tarayıcıda uzun süredir Vary'nin başına gelen en önemli yeniliklerden biridir. Accept-Encoding
ve Accept-Language
Et-Dil'den farklı olarak, İstemci İpuçları, bir kullanıcı web sitenizde dolaşırken düzenli olarak değişebilecek değerleri, özellikle aşağıdakileri açıklar:
-
DPR
Cihaz piksel oranı, ekranın piksel yoğunluğu (kullanıcının birden fazla ekranı varsa değişebilir) -
Save-Data
Kullanıcının veri tasarrufu modunu etkinleştirip etkinleştirmediği -
Viewport-Width
Geçerli görünümün piksel genişliği -
Width
Fiziksel piksellerde istenen kaynak genişliği
Bu değerler yalnızca tek bir kullanıcı için değişmekle kalmaz, aynı zamanda genişlikle ilgili olanların değer aralığı da geniştir. Bu nedenle, Vary
bu başlıklarla tamamen kullanabiliriz, ancak önbellek verimliliğimizi düşürme ve hatta önbelleğe almayı etkisiz hale getirme riskiyle karşı karşıyayız.
Anahtar Başlık Önerisi
İstemci İpuçları ve diğer son derece ayrıntılı başlıklar, Mark'ın üzerinde çalışmakta olduğu Anahtar adlı bir teklife katkıda bulunur. Birkaç örneğe bakalım:
Key: Viewport-Width;div=50
Bu, yanıtın Viewport-Width
istek başlığının değerine göre değiştiğini, ancak 50 pikselin en yakın katına yuvarlandığını söylüyor!
Key: cookie;param=sessionAuth;param=flags
Bu başlığı bir yanıta eklemek, iki belirli tanımlama bilgisini değiştirdiğimiz anlamına gelir: sessionAuth
ve flags
. Değişmedilerse, bu yanıtı gelecekteki bir istek için yeniden kullanabiliriz.
Dolayısıyla, Key
ve Vary
arasındaki temel farklar şunlardır:
-
Key
, başlıklar içindeki alt alanlarda değişiklik yapılmasına izin verir, bu da birdenbire çerezlerde değişiklik yapmayı mümkün kılar, çünkü yalnızca bir çerezde değişiklik yapabilirsiniz - bu çok büyük olur; - Önbellek isabeti şansını artırmak için bireysel değerler aralıklar halinde toplanabilir , bu özellikle görünüm alanı genişliği gibi şeyler üzerinde değişiklik yapmak için kullanışlıdır.
- aynı URL'ye sahip tüm varyasyonlar aynı anahtara sahip olmalıdır. Bu nedenle, bir önbellek, halihazırda bazı varyantları bulunan bir URL için yeni bir yanıt alırsa ve yeni yanıtın
Key
başlık değeri, bu mevcut varyantlardaki değerlerle eşleşmiyorsa, tüm varyantlar önbellekten çıkarılmalıdır.
Yazma sırasında, hiçbir tarayıcı veya CDN Key
desteklemez, ancak bazı CDN'lerde gelen başlıkları birden fazla özel başlığa bölerek ve bunlarda değişiklik yaparak aynı etkiyi elde edebilirsiniz (bkz. Fastly”), bu nedenle tarayıcılar, Key
etki yaratabileceği ana alandır.
Tüm varyasyonların aynı anahtar reçeteye sahip olma şartı biraz sınırlayıcıdır ve spesifikasyonda bir tür “erken çıkış” seçeneği görmek istiyorum. Bu, "Kimlik doğrulama durumuna göre değişir ve oturum açıldıysa tercihlere göre değişir" gibi şeyler yapmanızı sağlar.
Varyant Önerisi
Key
güzel bir genel mekanizmadır, ancak bazı başlıkların değerleri için daha karmaşık kuralları vardır ve bu değerlerin anlamlarını anlamak, önbellek varyasyonunu azaltmanın otomatik yollarını bulmamıza yardımcı olabilir. Örneğin, iki isteğin farklı Accept-Language
değerleriyle geldiğini, en-gb
ve en-us
olduğunu hayal edin, ancak web siteniz dil çeşitliliğini destekliyor olsa da, yalnızca bir "İngilizceniz" var. ABD İngilizcesi isteğine yanıt verirsek ve bu yanıt bir CDN'de önbelleğe alınırsa, Accept-Language
değeri farklı olacağından ve önbellek daha iyi bilecek kadar akıllı olmadığından, Birleşik Krallık İngilizcesi isteği için yeniden kullanılamaz. .
Büyük bir hayranlıkla Varyantlar önerisine girin. Bu, sunucuların hangi varyantları desteklediklerini tanımlamalarını sağlayarak önbelleklerin hangi varyasyonların gerçekte farklı ve hangilerinin aynı olduğu konusunda daha akıllı kararlar vermesini sağlar.
Şu anda, Varyantlar çok erken bir taslaktır ve Accept-Encoding
ve Accept-Language
ile yardımcı olmak için tasarlandığından, kullanışlılığı tarayıcı önbelleklerinden ziyade CDN'ler gibi paylaşılan önbelleklerle sınırlıdır. Ancak Key
ile güzel bir şekilde eşleşir ve önbellek varyasyonunun daha iyi kontrolü için resmi tamamlar.
Çözüm
Burada öğrenilecek çok şey var ve tarayıcının kaputun altında nasıl çalıştığını anlamak ilginç olsa da, ondan damıtabileceğiniz bazı basit şeyler de var:
- Çoğu tarayıcı
Vary
bir doğrulayıcı olarak ele alır. Birden çok farklı varyasyonun önbelleğe alınmasını istiyorsanız, bunun yerine farklı URL'ler kullanmanın bir yolunu bulun. - Tarayıcılar, HTTP/2 server push kullanılarak gönderilen kaynaklar için
Vary
yok sayar, bu nedenle, gönderdiğiniz hiçbir şeye göre değişiklik yapmayın. - Tarayıcıların bir ton önbelleği vardır ve farklı şekillerde çalışırlar. Önbelleğe alma kararlarınızın, özellikle
Vary
bağlamında her birinde performansı nasıl etkilediğini anlamaya çalışmakta fayda var. -
Vary
, olabileceği kadar kullanışlı değil veKey
İstemci İpuçları ile eşleştirilmesi bunu değiştirmeye başlıyor. Bunları ne zaman kullanmaya başlayabileceğinizi öğrenmek için tarayıcı desteğini takip edin.
İlerleyin ve değişken olun.