Ich speichere dynamisch generierte Seiten (PHP-FPM, NGINX) zwischen und habe Lack vor mir, das funktioniert sehr gut.
Sobald das Cache-Timeout erreicht ist, sehe ich Folgendes:
- Seite für neue Kundenanfragen
- Lack erkennt das Cache-Timeout
- Kunde wartet
- Lack holt neue Seite aus dem Backend
- Lack liefert neue Seite an den Client (und hat auch Seite für die nächste Anfrage zwischengespeichert, die es sofort erhält)
Was ich tun möchte ist:
- Client-Anforderungsseite
- Lack erkennt das Timeout
- Lack liefert alte Seite an den Kunden
- Lack holt neue Seite aus dem Backend und legt sie im Cache ab
In meinem Fall ist es keine Site, auf der veraltete Informationen ein so großes Problem darstellen, insbesondere nicht, wenn es sich um ein Cache-Timeout von wenigen Minuten handelt.
Ich möchte jedoch nicht, dass der bestrafte Benutzer in der Schlange steht und etwas Sofortiges liefert. Ist das irgendwie möglich?
Zur Veranschaulichung hier eine Beispielausgabe der 5-minütigen Belagerung meines Servers, die für den Cache für eine Minute konfiguriert wurde:
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
...
Ich habe die Hunderte von Anfragen, die eingegangen sind, ausgelassen 0.02
. Aber es macht mir immer noch Sorgen, dass es Benutzer geben wird, die fast 2 Sekunden auf ihren rohen HTML-Code warten müssen.
Können wir es hier nicht besser machen?
(Ich bin beim Cache auf Varnish Send gestoßen . Es klang ähnlich, aber nicht genau das, was ich versuche.)
Lösung
Die Antwort von Shane Madden enthielt die Lösung, aber ich habe sie nicht sofort erkannt. Es gab ein weiteres Detail, das ich nicht in meine Frage aufgenommen habe, weil ich dachte, es sei nicht relevant, aber tatsächlich ist es das.
Die CMS-Lösung, die ich derzeit verwende, verfügt über einen Lackdatenbank-Listener und kann somit Lack benachrichtigen, um Seiten zu sperren, deren Inhalt sich geändert hat. Es wurde eine PURGE
Anfrage mit einem regulären Ausdruck gesendet, um bestimmte Seiten zu sperren.
Zusammenfassend gibt es zwei Fälle, in denen ich unglückliche Benutzer hatte:
- Die normale Lack-TTL einer Seite läuft ab
- Backend-Benutzer ändern den Inhalt. Dadurch wird eine Bereinigungsanforderung an den Lack gesendet
In beiden Fällen habe ich "unglückliche" Benutzer. Im zweiten Fall wird dies durch die Tatsache gemildert, dass Backend-Benutzer die Seite normalerweise überprüfen, nachdem sie geändert wurde. aber nicht unbedingt.
Trotzdem habe ich für den zweiten Fall eine Lösung erstellt (ja, mir ist klar, dass diese Frage mit der Suche nach einer Antwort für den ersten Fall begann ... schlecht formulierte Frage meinerseits):
Anstatt eine Bereinigungsanforderung zu senden, habe ich den Shanes-Vorschlag verwendet und die VCL so angepasst, dass mein Lackdatenbank-Listener eine spezielle Anforderung zum Abrufen einer Seite mit der hash_always_miss
Einstellung auf senden kann true
.
Mit der aktuellen Architektur habe ich nicht wirklich den Luxus, eine echte asynchrone Anfrage zu stellen, aber mit Hilfe von Wie mache ich eine asynchrone GET-Anfrage in PHP? Ich konnte eine GET-Anforderung zum Lackieren erstellen, die nicht auf das Laden der Seite wartet, aber gut genug ist, um den Lack auszulösen, um die Seite aus dem Backend abzurufen und zwischenzuspeichern.
Der Nettoeffekt war, dass der Datenbank-Listener die Anfrage an Lack gesendet hat und während ich die bestimmte Seite abgefragt habe, meine Anfragen nie "unglücklich" gemacht wurden, aber sobald Lack die Seite vollständig aus dem Backend abgerufen hat (dies kann zwischen 300 ms und 2 s liegen) war plötzlich da.
Ich muss noch eine Lösung finden, um die gleichen Probleme zu vermeiden, wenn die normale TTL ausgeht, aber ich denke, die Lösung ist auch genau so, wie Shane es vorschlägt: Wenn ich wget verwende, um das auszulösen hash_always_miss
, muss ich nur klug genug sein, um eine Liste zu erhalten von Seiten muss ich aktualisieren.