contao / core

Contao 3 → see contao/contao for Contao 4
GNU Lesser General Public License v3.0
490 stars 213 forks source link

Seitencache und Spracherkennung #7618

Closed dmolineus closed 9 years ago

dmolineus commented 9 years ago

Nach dem Update von einer Contao-Installation 3.3.7 auf 3.4.3 funktionierte der Seiten-Cache nicht mehr. Nach einigen Debuggen fiel mir auf, dass Contao nun die Seite mit "de-DE" cachte, in den Seiteneinstellungen jedoch das Sprachkürzel "de" hinterlegt war.

Daher hat Contao die Seite nicht aus dem Cache geladen obwohl die Seite auch als Sprachenfallback arbeitet.

Durch die Umstellung in den Seiteneinstellungen besteht jedoch das Problem, dass ein Browser, der lediglich ein "de" als Accept-Language sendet, wieder eine ungecachte Seite lädt.

dmolineus commented 9 years ago

Das ist ein grundsätzliches Problem bei einer nicht unterstützten und damit gecachten Sprache (Accept-Language). Diese werden immer ungecacht ausgeliefert anstatt die gecachte Fallbackseite zu laden.

Toflar commented 9 years ago

@dmolineus PR? ;)

dmolineus commented 9 years ago

Wenn wir uns im Voraus auf eine Lösung verständigen können, mach ich das. Mein Vorschlag ist folgender:

Dadurch erspart man sich eine Datenbankabfrage beim Laden vom Cache, um die Standardsprache zu ermitteln. Die doppelten Cache-Einträge sind imho zu verschmerzen.

aschempp commented 9 years ago

Woher soll das System denn wissen dass für empty.LANG keine Seite existiert, oder ob die einfach noch nicht gecacht wurde?

dmolineus commented 9 years ago

Woher soll das System denn wissen dass für empty.LANG keine Seite existiert, oder ob die einfach noch nicht gecacht wurde?

Danke für den Einwand, hatte ich nicht bedacht.

Ich seh erstmal keine Möglichkeit ohne Datenbankabfrage dies festzustellen (es sei denn man hat eine Cache-Datei mit allen verfügbaren Sprachen).

Toflar commented 9 years ago

@leofeyer up for discussion-Label?

leofeyer commented 9 years ago

Eine Datenbank-Abfrage kommt jedoch beim Laden aus dem Cache keinesfalls in Frage.

BugBuster1701 commented 9 years ago

(es sei denn man hat eine Cache-Datei mit allen verfügbaren Sprachen).

bzw. der Rootseiten Sprach Definition inkl. Fallbacksprache. Dann käme man zumindest für den Fall hier https://github.com/contao/core/issues/7650 schon weiter.

leofeyer commented 9 years ago

Wir haben heute auf Mumble darüber gesprochen, verstehen aber das Problem nicht so ganz. Könntest Du uns das nochmal erklären bzw. beim nächsten Mumble-Termin mit uns besprechen?

dmolineus commented 9 years ago

Es ist das gleiche Problem, wie @amenk in #7650 detaillierter beschrieben hat und hier ja auch verlinkt ist. Doch gern noch einmal konkreter.

  1. Der Cache ist aktiviert und es wird die Startseite angesurft.
  2. Diese wird mit den Spracheinstellung gecacht (de).
  3. Der Browser ruft die Startseite auf mit folgenden Accept-Language Header de-DE,de.
  4. In outputFromCache wird nun empty.de-DE versucht aus dem Cache zu laden, was nicht existiert.

Dies tritt auch auf, wenn Accept-Language Header en ist und dafür keine gecachte Datei existiert.

Die Probleme dabei sind:

  1. Es findet kein Mapping zwischen de-DE und de statt, auch nicht in die andere Richtung.
  2. Nicht existierende Sprachen für die der Fallback greift werden nie gecacht ausgeliefert.

Der ursprünglich vermutete Zusammenhang mit dem Update auf Contao 3.4 konnte nicht bestätigt werden. Der Fehler wurde jedoch erst durch den massiven Performance-Verlust nach dem Update sichtbar (Ladezeit ~0.9sec gegebüber ~0.35sec davor).

Gern erläutere ich es auch bei einem nächsten Mumble-Termin, bin aber zu den 19 Uhr Terminen donnerstags nicht verfügbar.

leofeyer commented 9 years ago

Meiner Meinung nach vertust Du Dich in Punkt 2:

Diese wird mit den Spracheinstellung gecacht (de).

Wenn die Primärsprache aus dem Accept-Language-Header de-DE ist, wird die Seite unter empty.de-DE im Cache abgelegt.

aschempp commented 9 years ago

Ich habe mir den Code nicht angesehen, aber ich bin der Überzeugung die Seite wird unter empty.de (nämlich der Sprache der Root-Seite) gecacht.

dmolineus commented 9 years ago

Wenn die Primärsprache aus dem Accept-Language-Header de-DE ist, wird die Seite unter empty.de-DE im Cache abgelegt.

Nein, wird sie nicht. https://github.com/contao/core/blob/master/system/modules/core/classes/FrontendTemplate.php#L204

Wäre auch fahrlässig, da man durch einen gefakten Header den Cache zuspammen könnte.

leofeyer commented 9 years ago

Da habt ihr beide Recht.

amenk commented 9 years ago

Ich denke man sollte wie in https://github.com/contao/core/issues/7618#issuecomment-75456963 beschrieben die Root Seiten und Fallback Struktur separat cachen.

aschempp commented 9 years ago

Das nützt nichts, weil wir ja nicht wissen ob es eine Sprache de-DE gibt und sie einfach noch nicht gecacht wurde…

amenk commented 9 years ago

Ich dachte jetzt an ein Array, Serialisiert in einer Datei abgelegt in der die Root Seiten und deren Sprachen gecacht werden. So braucht man keine Datenbankabfrage. Ein andere Möglichkeit wird es denke ich nicht geben, denn man braucht ja die Infos über die Fallback Struktur. Statt dem Array könnte man auch leere Dateien mit den anderen Sprachen anlegen um sie als "Existent aber nicht gecacht" zu markieren und dann bei Bedarf cachen.

dmolineus commented 9 years ago

Ich dachte jetzt an ein Array, Serialisiert in einer Datei abgelegt in der die Root Seiten und deren Sprachen gecacht werden. So braucht man keine Datenbankabfrage. Ein andere Möglichkeit wird es denke ich nicht geben, denn man braucht ja die Infos über die Fallback Struktur.

Genau das war auch meine Idee, die ich oben vorgeschlagen hatte.

amenk commented 9 years ago

Und generell braucht man wohl noch irgendwo ein Stück Code was von de-DE auf de mappt, oder?

dmolineus commented 9 years ago

Ein Mapping zwischen de <-> de-DE gäre gut, auch wenn nicht ganz trivial. Angenommen man hat eine Seite mit de-AT und eine mit de-DE stellt sich die Frage auf was de dann gemappt wird.

leofeyer commented 9 years ago

Behoben in ed1a73a487e4a1c65043734df9c214fe3bd1c75b. Beim Aufbau des internen Cache wird jetzt eine Mapper-Datei angelegt, die bestehende Sprachen plus Fallback-Sprache auf die jeweiligen Cache-Keys mappt. Nur wenn der interne Cache gar nicht aufgebaut ist, fällt der Frontend-Controller auf die bisherige Lösung mit der ersten akzeptierten Sprache zurück.

leofeyer commented 9 years ago

@all Bitte testen und Feedback geben. @contao/developers Sollen wir das in die 3.2 portieren?

Toflar commented 9 years ago

@contao/developers Sollen wir das in die 3.2 portieren?

Ich stimme für Nein. Begründung:

leofeyer commented 9 years ago

@Toflar So einfach ist das nicht.

fritzmg commented 9 years ago

@Toflar

Das aktuelle Verhalten ist zwar nicht korrekt, beeinflusst aber die Funktionalität nicht wesentlich.

Auf einer Seite, die nur einen Seitenbaum hat und als Sprache de festgelegt hat + Sprachenfallback, bekommt ein User nie eine Seite aus dem Cache von Contao, wenn er mit einem HTTP Accept-Language header ungleich de daher kommt.

Wenn eine Contao Seite von der Cache Funktionalität abhängig ist (warum auch immer) besteht imho eine starke Beeinträchtigung.

Toflar commented 9 years ago

Es geht ja nicht um die Frage ob's ein Bug ist oder nicht. Selbstverständlich ist es einer und wenn es ein Bug ist dann beeinflusst der selbstverständlich auch die Funktionalität. Ist doch logisch. Ich hab nur gesagt er beeinträchtigt die Funktionalität von Contao nicht wesentlich weil es keinen Grund gibt, warum der Cache auf die Funktionsweise einen Einfluss haben sollte. Er reduziert nur Server- und/oder Bandwidth-Load.

fritzmg commented 9 years ago

Ja ok, verstehe.

Würde auch verstehen, wenn dieser Fix letztendlich auch erst in der nächsten LTS version auftaucht (wie von leofeyer erwähnt).

aschempp commented 9 years ago

Auf einer Seite, die nur einen Seitenbaum hat und als Sprache de festgelegt hat + Sprachenfallback, bekommt ein User nie eine Seite aus dem Cache von Contao, wenn er mit einem HTTP Accept-Language header ungleich de daher kommt.

Nicht ganz, das trifft natürlich nur auf die Startseite zu (ev. nur falls diese ein Alias index hat?).

aschempp commented 9 years ago

Fände auch dass das in die 3.5 sollte. Es ist nicht wirklich ein Bug, sondern ein known limitation (siehe #7650)

fritzmg commented 9 years ago

Nicht ganz, das trifft natürlich nur auf die Startseite zu (ev. nur falls diese ein Alias index hat?).

Ah ok, da hab ich wohl zu wenig getestet :)

dmolineus commented 9 years ago

Ich hab nur gesagt er beeinträchtigt die Funktionalität von Contao nicht wesentlich weil es keinen Grund gibt, warum der Cache auf die Funktionsweise einen Einfluss haben sollte

Auf die Funktionsweise nicht, auf die wahrgenommene Performance jedoch schon. Gerade wenn man auf der Startseite ein weniger perfomantes Contao Modul einsetzt (Events-Modul mit > 5000 Events), hat man schnell Ladezeiten, die wenig erfreulich sind.

Toflar commented 9 years ago

Das ist richtig. Das wäre dann aber, wie gesagt, der Speed und nicht die Funktionsweise :-) Ich würd’s nur gerne in der 3.5 haben, weil’s ein grösserer Change ist und die 3.5 sowieso im Mai kommt. Bleibt es in der 3.4 in einem Bugfix-Release so muss es natürlich auch auf die 3.2 gebackported (Denglish ftw) werden :)

dmolineus commented 9 years ago

Für mich wäre 3.5 auch in Ordnung. In den Projekten, wo dies ein Problem war, läuft eh seit längerem ein Workaround, sodass das Problem dort nicht mehr relevant ist.

leofeyer commented 9 years ago

Hab die Änderungen in der 3.4 zurückgenommen und nach 3.5 portiert.

fritzmg commented 9 years ago

@dmolineus : wie sieht dieser workaround aus? wäre vielleicht auch für andere interessant

dmolineus commented 9 years ago

@fritzmg Dieser Workaround macht nichts anderes, als über den getCacheKey Hook den Cache-Key zu manipulieren. In meinem Fall, wo es nur eine Sprache gibt, sehr einfach.

    public function hookGetCacheKey($cacheKey)
    {
        if (\Environment::get('request') === '' || \Environment::get('request') === 'index.php') {
            $cacheKey = 'empty.de-DE';
        }

        return $cacheKey;
    }

Wenn man mehrere Sprachen hat, müsste man hier halt das Mapping zwischen den 2 und 5 Zeichen Sprache-Codes und auf die Fallback-Sprache mit implementieren.

SpeGal commented 9 years ago

There is still a bug in this issue! See #7909. Page caching doesn't work with multiple languages!

fritzmg commented 7 years ago

This is still a problem in Contao 3.5.25 (see https://community.contao.org/de/showthread.php?66351-Startseite-nicht-im-Seitencache for example).

Reproduction

  1. Create a new Contao installation.
  2. Create a theme and page layout.
  3. Create a new website root with the language set to en.
  4. Set the previously generated page layout.
  5. Enable the page cache within the website root.
  6. Create a start page with alias index within the website root.
  7. For debugging purposes, add echo 'FROM CACHE'; here and echo 'NOT FROM CACHE'; here.
  8. Set the primary Accept-Language of your browser to de.
  9. Clear the internal cache and do not rebuild (it won't work with the internal cache either, but that is a different issue: #8694).
  10. Open the front end (without a request parameter) in a new browser session or while being logged out of the back end. You will see NOT FROM CACHE.
  11. Reload the page. You will see NOT FROM CACHE again, even though a cache file is present.
fritzmg commented 7 years ago

This is due to the fact, that Contao will search for a cache key that consists of …/empty. plus the primary Accept-Language here: system/modules/core/controllers/FrontendIndex.php#L367-L371. If the page's language differs from that, the page cannot be served from cache.

However, since this only happens, when the internal cache is not active (after applying #8695), I consider this not much of an issue. You are unlikely to not use the internal cache in the productive environment.