[TYPO3-german] Caching von Webserviceantworten

f zuerker fzuerker at mail.uni-mannheim.de
Mon Aug 14 07:56:14 CEST 2017


Ok, mit so einer ausführlichen Atnwort hab ich nicht gerechnet. Danke!

Quote: Stephan Schuler wrote on Fri, 11 August 2017 14:02
----------------------------------------------------

> Eine Variante wäre, die Remote-Daten als lokale Domäne abzubilden und per Scheduler einen Import zu bauen. Wenn z.B. ein beliebiges JSON- oder XML-Format verwendet wird um Daten bereitzustellen die in TYPO3 als News angezeigt werden sollen bietet es sich ja an, alle paar Minuten die Daten remote abzufragen und in lokale News-Records zu überführen.
> 
> Der Vorteil daran ist natürlich, dass man keinen gesonderten Renderingprozess für diese News konfigurieren muss, wenn es ohnehin schon anderweitige, lokale News gibt.

Das ist der Weg, den ich so jetzt auch gegangen wäre.
Vorab zum Verständnis grad nochmal was ich brauche: Ich möchte eine Extension bauen, die den Redakteuren ein Frontend Plugin zur Verfügung stellt, welches sie auf beliebigen Seiten einfügen können. Dieses Plugin soll letztendlich Daten eines Webservice (genauer handelt es sich dabei um Veranstaltungsdaten (Termin, Ort, etc.)) tabellarisch aufbereiten und anzeigen. Der Redakteuer hätte in der Plugin Konfiguration gewisse Einstellungsmöglichkeiten, was genau angezeigt werden soll (aus diesen Einstellungen wird die Request für den Webservice gebaut). Die angezeigten Daten müssen von Zeit zu Zeit aktualisiert werden (nehmen wir als Richtwert mal an das die Daten immer 1 Stunde lang gültig sind).
Stellt sich für mich nur noch die Frage, ob ich die Aktualisierung der Remote-Daten per Scheduler oder im Controller durchführe. Ersteres scheint mir eigentlich der sauberere Weg zu sein, allerdings sehe ich beim Controller den Vorteil, dass nur Einträge aktualisiert werden, die auch abgefragt werden. Seiten mit dem Plugin, die nicht aufgerufen werden, müssen ja nicht aktuell sein. Nachteil wäre halt, dass es jede Stunde einen Nutzer trifft, der einige Sekunden warten muss, bis die Remote-Daten neu abgefragt wurden.



> Auch wenn man in eine lokale Suche die Remote-Daten integrieren möchte bietet sich dieser Schritt an. Wenn man erst einen Import von einer Remote-API in lokale Datensätze durchführt, kann im Folgeschritt z.B. ein Solr-Indexing-Task die Daten in den Solr schaufeln und sie sind im Frontend über die Suche verfügbar.
> 
> Dabei sollte der Import natürlich über den TYPO3 DataHandler durchgeführt werden, weil das die zentrale Stelle ist, die sowohl eine für Redakteure nachvollziehbare History erzeugt also auch der API-Call, an den sich wiederum Record-Indexer wie eben Solr hängen um innerhalb von TYPO3 über Datenänderungen informiert zu werden. Auch was Caching innerhalb einer TYPO3-Seite betrifft (Cache-Tags im Caching-Framework) ist die Verwendung des DataHandler dringend angeranten.

Eine Verfügbarkeit der Daten über eine Suche ist nicht nötig.



> Eine weitere Möglichkeit ist ein Runtime-Cache. Der API-Aufruf ist sicherlich in irgendeiner Form ein HTTP GET-Request. Das heißt hier gibt es eine URL aus der sich ein Cache-Identifier ableiten lässt sowie einen Response-Body der der Cache-Content sein kann.
> Hier rate ich dringend dazu, nicht irgendeine selbst erfundene Datenbankstruktur zu verwenden, sondern das Caching-Framework. Für die Speicherung der Daten gibt es unterschiedliche Backends, nämlich u.a. dateibasiert, datenbankbasiert, memcache oder redis. Je nach Bedarf und Verfügbarkeit. Dem Konsumenten des Caches gegenüber stellt man die Daten dan entweder über das Variable-Frontend zur Verfügung (z.B. wenn es sich um Array oder Objekte handelt) oder über das String-Frontend (wenn der Konsument den Text-Body bekommen soll).
> Wenn der Cache richtig konfiguriert ist, lässt er sich über die „Clear Cache"-Buttons im Backend rechts oben ganz einfach leeren, wodurch das auch von Redakteuren bedient werden kann. Oder auch ein „Clear all Caches" wie man es ja vermutlich im Rahmen jedes Code-Deployments anstößt (Stichwort CLI-API!) nimmt das Caching-Framework, man muss sich also nicht selbst darum kümmern.

Ja, der Webservice wird über eine SOAP-Request angesprochen. Werde mir diese Möglichkeit mal genauer ansehen.


 
> In beiden Fällen ist natürlich kein Weg beschrieben, wie Inhaltsänderungen des Providers an TYPO3 kommuniziert werden können. Das heißt, dass Du Dir eine Cache-Lifetime ausdenken musst die im Zweifelsfall zu kurz oder zu lang ist. Eine Lifetime von wenigen Minuten könnte dafür sorgen, dass Du trotzdem an ein anbieterseitiges Request-Limit stößt. Eine Lifetime von mehreren Minuten dagegen sorgt immer für panische Anrufe von Redakteuren, warum die Inhaltsänderung nicht sofort auch in TYPO3 sichtbar ist. Hier sollte es im Idealfall Empfehlungen des API-Providers geben an die man sich halten kann. Dann lassen sich diese Empfehlungen dem Kunden kommunizieren und die panischen Redakteure können mit Fakten beruhigt werden.
> 
> 
> Wenn es sich um einen HTTP GET-Request handelt der seinerseits Cache-Header enthält, könnte man sich auch an die halten. Wenn z.B. ein „Cache-Control: Max-Age" kommt kann ich ausrechnen wie lange ich diesen Wert cachen darf. Wenn ein „Cache-Control: Private" kommt brauch ich mit dem Caching gar nicht anfangen. Mir ist hierzu aber nichts bekannt das das durch eine Library abdecken würde. Wenn das im Rahmen Deines Projekts entsteht schreit das also nach einer Veröffentlichung.

Der Webservice liefert leider keinen Cache-Header.



> Wenn lediglich innerhalb eines einzigen TYPO3-Prozesses ein Request gecacht werden soll, würde ich trotzdem das Caching-Framework verwenden. Gemeint ist, wenn der gleiche GET-Request z.B. durch ViewHelper mehrmals vom gleichen TYPO3-Prozess abgeschickt wird.
> Man könnte zwar auf den ersten Blick auf die Idee kommen, einfach eine Singleton-Klasse zu schreiben die den Request unterdrückt, wenn für die URL bereits eine Response in einer Instanzvariable steht. Das wirft man allerdings komplett weg, wenn man das Caching über mehrere Prozesse ausdehnen will.
> Besser man verwendet gleich das Caching-Framework und stellt als Backend erst mal das „TransientMemoryBackend" ein. Das ist nur innerhalb eines PHP-Prozesses gültig, d.h. der nächste Click startet wieder mit einem leeren Backend und macht einen neuen HTTP-Request. Wenn man allerdings später das Caching über mehrere Prozesse strecken möchte, gibt man einfach ein anderes Backend über die LocalConfiguration oder EnvironmentConfiguration an, ohne seinen PHP-Code anfassen zu müssen. Auch lassen sich so z.B. ein Stagingserver mit TransientMemoryBackend (weil der eh keine nennenswerte Last aber dafür ungeduldige Spielkinder als Redakteure hat) und ein Produktivserver mit MamcacheBackend (weil der unter hoher Last fährt und es ohnehin nicht so wichtig ist, ob Kunden nun fünf Minuten früher oder später an die aktualisierten Daten kommen) betreiben, einfach, indem über die individuellen EnvironmentConfiguration.php-Dateien unterschiedliche Backends oder unterschiedliche Lifetimes konfiguriert sind.
> 
> 
> In allen Fällen mit Runtime-Cache (egal ob mit Caching-Framework oder selbstgebastelt) muss das aber natürlich auch in irgendeiner Form mit dem Caching der TYPO3-Seite selbst synchronisiert werden. Es bringt überhaupt nichts, wenn mein Caching-Framework die Daten nach fünf Minuten wegwirft, aber mein TYPO3 Page-Cache einen Tag lang die gleiche Seite ausliefert. Wie das jetzt am sinnvollsten geht hängt wiederum vom Anwendungsfall ab. Und „No-Cache" ist natürlich keine Option.



More information about the TYPO3-german mailing list