Apakah Vary Header

Vary adalah salah satu header respons HTTP yang paling kuat. Jika digunakan dengan benar, ia dapat melakukan hal-hal yang luar biasa. Sayangnya, header ini sering digunakan secara tidak benar, yang dapat menyebabkan rasio klik yang buruk. Lebih buruk lagi, jika tidak digunakan menurut aturan, maka hasilnya adalah konten yang salah bisa terkirim.

Di sini, saya akan menjelaskan header Vary menggunakan kasus penggunaan paling umum: kompresi.

Jika Anda menggunakan mod_deflate Apache, header Vary yang benar secara otomatis ditambahkan kepada respons Anda.

Anatomi Permintaan HTTP

Biasanya, ketika sebuah permintaan masuk ke salah satu cache blog ini, hanya dua bagian dari permintaan yang digunakan untuk menemukan objek di cache: path (dan string query, jika ada), dan header Host.

Ini adalah permintaan biasa untuk http://example.com/somepage .php:

GET /somepage.php HTTP / 1.1 
Host: contoh.com 
Connection: keep-alive 
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.125 Safari/537.36
Accept-Language: en-US,en;q=0.8
Accept-Encoding: gzip,deflate,sdch

Seperti yang ditunjukkan di atas, peramban mengirimkan banyak informasi bersama dengan URL. Header Accept memberitahu Anda jenis konten apa yang dibutuhkan oleh browser, User-Agent menentukan versi apa browser itu, Accept-Language berisi daftar bahasa (dan dialek) yang telah dikonfigurasi pengguna, dan Accept-Encoding menunjukkan kompresi schema (Skema) mana yang didukung browser.

Untuk tujuan praktis, kami hanya fokus gzipdeflate sebagai yang utama, dan sdchtidak digunakan oleh siapa pun kecuali Google.

Kompresi di Tempat Kerja

Situasi hipotetis: Anda memiliki web server tanpa mod_deflate, tetapi Anda sudah tahu bagaimana melakukan kompresi gzip di PHP. Jadi ketika Anda melihat gzipdi Accept-Encodingheader, Anda mengatur Content-Encoding: gzipheader untuk memberi tahu browser apa yang Anda lakukan, dan Anda mengkompres / memadatkan penanggapan body.

Sekarang bayangkan bahwa server ini adalah asal dari layanan Cepat, dan halaman ini adalah salah satu yang dapat kita cache. Apa yang akan terjadi jika browser yang tidak mengerti kompresi adalah yang pertama untuk meminta halaman ini? Kami akan berakhir dengan halaman yang tidak terkompresi di cache kami.

Apakah ini masalah? Hanya yang kecil. Jika browser yang memahami permintaan kompresi halaman ini, itu akan mendapatkan versi terkompresi dari cache kami, dan akan baik-baik saja. Tetapi versi tidak terkompresi lebih besar, sehingga akan membutuhkan lebih banyak bandwidth untuk mengirim, sehingga pengiriman lebih lambat untuk pengguna akhir dan biaya yang lebih tinggi untuk Anda.

Masalah yang lebih besar adalah ketika permintaan pertama untuk suatu objek berasal dari browser yang melakukan kompresi, dan kita berakhir dengan versi terkompresi di cache kami. Sekarang, ketika browser datang yang tidak mengerti kompresi, ia mendapatkan versi terkompresi dan tidak tahu apa yang harus dilakukan selain menampilkan omong kosong.

Bervariasi untuk Rescue

Ada dua cara untuk memperbaikinya. Pertama, Anda dapat mengubah kunci cache dalam konfigurasi Cepat Anda, tetapi itu akan menyebabkan masalah tambahan:

  1. Anda harus membersihkan kedua versi terkompresi dan tidak terkompresi secara terpisah.
  2. Kesalahan yang dibuat di sini dapat menyebabkan semua URL mengembalikan satu objek yang sama.

Sebagai gantinya, Anda dapat menggunakan header Vary dan menghindari kedua masalah ini.

Header Vary memberitahu setiap cache HTTP bagian mana dari header permintaan, selain path dan header Host, untuk memperhitungkan ketika mencoba untuk menemukan objek yang tepat. Ia melakukan ini dengan daftar nama-nama header yang relevan, yang dalam hal ini adalah Accept-Encoding. Jika ada beberapa tajuk yang mempengaruhi respons, mereka semua akan dicantumkan dalam satu tajuk, dipisahkan oleh koma.

Header respon untuk respons terkompresi seharusnya terlihat seperti ini:

HTTP / 1.1 200 OK 
Konten-Panjang: 3458 
Cache-Control: max-age = 86400 
Content-Encoding: gzip Vary: Accept-Encoding

Dan untuk respons yang tidak terkompresi, header respon terlihat seperti:

HTTP / 1.1 200 OK 
Konten-Panjang: 8365 
Cache-Control: max-age = 86400 Vary: Accept-Encoding

Perhatikan bahwa header Vary ada dalam respons terlepas dari apakah kompresi digunakan atau tidak.

Kenapa ini? Mari kita lihat apa yang terjadi ketika itu benar-benar ada.

Pertama, permintaan datang untuk sebuah objek, tanpa header Terima-Pengkodean. Objek tidak dalam cache, jadi kami memintanya dari asalnya, yang mengembalikannya dengan header Vary. Ketika Cepat menyimpan objek dalam cache, header Vary dicatat, dan nilai dari header yang relevan dari permintaan disimpan juga.

Jadi sekarang ada objek di cache yang memiliki bendera kecil di atasnya yang mengatakan “hanya untuk digunakan untuk permintaan yang tidak ada Accept-Encodingdalam permintaan.”

Sekarang, bayangkan ada browser yang mengerti kompresi dan mengirim permintaan seperti yang dijelaskan di atas. Pertama, kami mencari tahu dengan header dan jalur Host. Ini akan menemukan objek, tetapi permintaan memiliki header Terima-Pengkodean, diatur ke gzip,deflate,sdch, dan yang tidak cocok dengan bendera yang diletakkan pada objek ini.

Jadi Cepat pergi ke asal Anda lagi, dan kali ini kita harus mendapatkan kembali versi terkompresi dari objek. Tanggapan ini kemudian disimpan dengan bendera yang mengatakan bahwa versi ini hanya boleh digunakan untuk permintaan Accept-Encoding: gzip,deflate,sdch.

Jika header Vary tidak ada di respon pertama, kita tidak akan tahu bahwa kita tidak bisa menggunakan objek cache untuk permintaan kedua.

Normalisasi

Anda mungkin bertanya-tanya apakah semua browser hari ini mengirim header Terima-Pengkodean yang sama.

Sayangnya, jawabannya tidak.

Saya mengambil sampel 100.000 permintaan pada salah satu cache kami, dan mendapat 44 header Terima-Pengkodean yang berbeda. (Bagi mereka yang tertarik dengan cara saya melakukannya, atau jumlahnya, lihat di sini )

Jika semua permintaan itu untuk URL yang sama, kami akan memiliki 44 versi “berbeda” di cache kami. Tetapi karena asalnya hanya dapat menghasilkan dua versi, satu jika gzipada Accept-Encodingdan satu jika tidak, itu 42 permintaan ke asal yang ingin kita hindari.

Karena asal hanya peduli apakah gzip ada atau tidak, mengapa kita tidak menormalkan header Terima-Pengkodean untuk mengandung gzipatau tidak ada sama sekali?

Hanya ada dua variasi header Accept-Encoding dalam permintaan kami, dan oleh karena itu kami hanya akan memiliki dua variasi objek dalam cache kami.

Ini mudah dilakukan dengan VCL kecil:

# do this only once per request
if (req.restarts == 0) {
  # normalize Accept-Encoding to reduce vary
  if (req.http.Accept-Encoding ~ "gzip") {
    set req.http.Accept-Encoding = "gzip";
  } else {
    unset req.http.Accept-Encoding;
  }
}

Anda mungkin masih ingin mendukung beberapa klien HTTP kuno, jadi mari kita tambahkan dukungan deflatejuga, dan mari pastikan Internet Explorer 6 tidak perlu berurusan dengan kompresi (ini sangat buruk dalam hal itu).

# do this only once per request
if (req.restarts == 0) {
  # normalize Accept-Encoding to reduce vary
  if (req.http.Accept-Encoding) {
    if (req.http.User-Agent ~ "MSIE 6") {
      unset req.http.Accept-Encoding;
    } elsif (req.http.Accept-Encoding ~ "gzip") {
      set req.http.Accept-Encoding = "gzip";
    } elsif (req.http.Accept-Encoding ~ "deflate") {
      set req.http.Accept-Encoding = "deflate";
    } else {
      unset req.http.Accept-Encoding;
    }
  }
}

Sepotong VCL sangat mirip dengan ini telah menjadi bagian dari Fastly Master VCL sejak perusahaan kami didirikan.

Tinggalkan komentar