Saya caching halaman yang dibuat secara dinamis (PHP-FPM, NGINX) dan ada pernis di depannya, ini bekerja dengan sangat baik.
Namun, setelah batas waktu cache tercapai, saya melihat ini:
- halaman permintaan klien baru
- varnish mengenali batas waktu cache
- klien menunggu
- pernis mengambil halaman baru dari backend
- varnish mengirim halaman baru ke klien (dan memiliki halaman di-cache juga, untuk permintaan berikutnya yang langsung mendapatkannya)
Yang ingin saya lakukan adalah:
- halaman permintaan klien
- pernis mengakui batas waktu
- pernis mengirimkan halaman lama ke klien
- pernis mengambil halaman baru dari backend dan memasukkannya ke dalam cache
Dalam kasus saya, ini bukan situs di mana informasi yang ketinggalan jaman adalah masalah besar, terutama tidak ketika kita berbicara tentang cache timeout beberapa menit.
Namun, saya tidak ingin menghukum pengguna untuk menunggu dalam antrean dan alih-alih mengirimkan sesuatu dengan segera. Apakah itu mungkin?
Sebagai ilustrasi, berikut adalah contoh hasil dari pengepungan 5 menit terhadap server saya yang dikonfigurasi untuk cache selama satu menit:
HTTP/1.1,200, 1.97, 12710,/,1,2013-06-24 00:21:06
...
HTTP/1.1,200, 1.88, 12710,/,1,2013-06-24 00:21:20
...
HTTP/1.1,200, 1.93, 12710,/,1,2013-06-24 00:22:08
...
HTTP/1.1,200, 1.89, 12710,/,1,2013-06-24 00:22:22
...
HTTP/1.1,200, 1.94, 12710,/,1,2013-06-24 00:23:10
...
HTTP/1.1,200, 1.91, 12709,/,1,2013-06-24 00:23:23
...
HTTP/1.1,200, 1.93, 12710,/,1,2013-06-24 00:24:12
...
Saya mengabaikan ratusan permintaan yang berjalan sekitar 0.02
. Tetapi saya masih khawatir bahwa akan ada pengguna yang harus menunggu hampir 2 detik untuk HTML mentah mereka.
Tidak bisakah kita melakukan yang lebih baik di sini?
(Saya menemukan Varnish kirim sementara cache , kedengarannya mirip tetapi tidak persis apa yang saya coba lakukan.)
Larutan
Jawaban dari Shane Madden berisi solusinya, tetapi saya tidak segera menyadarinya. Ada detail lain yang tidak saya sertakan dalam pertanyaan saya karena saya pikir itu tidak relevan, tetapi sebenarnya itu relevan.
Solusi CMS yang saya gunakan saat ini memiliki pendengar basis data pernis dan dengan demikian memiliki kemampuan untuk memberi tahu pernis untuk mencekal halaman yang isinya telah berubah. Itu mengirim PURGE
permintaan dengan beberapa regex untuk melarang halaman tertentu.
Singkatnya, ada dua kasus di mana saya mendapat pengguna yang tidak beruntung:
- TTL pernis normal halaman kedaluwarsa
- pengguna backend mengubah konten, ini mengirimkan permintaan pembersihan untuk pernis
Dalam kedua kasus saya memiliki pengguna "sial". Dalam kasus kedua ini diringankan oleh fakta bahwa pengguna backend biasanya memeriksa halaman setelah itu diubah; tapi belum tentu.
Namun demikian, untuk kasus kedua saya menciptakan solusi (ya, saya menyadari pertanyaan ini dimulai dengan mencari jawaban untuk kasus pertama ... pertanyaan yang dirumuskan dengan buruk di pihak saya):
Alih-alih mengirim permintaan pembersihan, saya menggunakan saran Shanes dan menyesuaikan VCL sehingga pendengar basis data pernis saya dapat mengirim permintaan khusus untuk mengambil halaman dengan hash_always_miss
set ke true
.
Dengan arsitektur saat ini saya tidak benar-benar memiliki kemewahan melakukan permintaan asinkron nyata, tetapi dengan bantuan Bagaimana cara membuat permintaan GET asinkron dalam PHP? Saya dapat membuat permintaan GET ke pernis yang tidak menunggu halaman dimuat tetapi cukup baik untuk memicu pernis untuk mengambil halaman dari backend dan menyimpannya.
Efek bersihnya adalah bahwa pendengar basis data mengirim permintaan untuk pernis dan ketika saya sedang polling halaman tertentu itu tidak pernah membuat permintaan saya "sial" tetapi sekali pernis mengambil halaman sepenuhnya dari backend (ini mungkin berkisar dari 300ms ke 2s) itu tiba-tiba ada di sana.
Saya belum menemukan solusi bagaimana menghindari masalah yang sama ketika TTL normal habis, tapi saya kira solusinya juga persis seperti yang disarankan Shane: menggunakan wget untuk memicu hash_always_miss
, saya hanya harus cukup pintar untuk mendapatkan daftar halaman saya harus menyegarkan.