Personal tools
You are here: Home Plone Book 14. Administration und Skalierung von Plone
Die maximale Bildbreite kann wie folgt gewählt werden:

14. Administration und Skalierung von Plone

Document Actions

Administration und Skalierung von Plone

In diesem Kapitel geht es um Aufgaben, um die Sie sich kümmern müssen, nachdem Sie Ihre Site aufgebaut haben und sie benutzen. Ich beginne mit der Administration einer Plone-Site, die prinzipiell ziemlich einfach ist. Danach beschreibe ich, wann und von welchen Dateien Sicherheitskopien angelegt werden sollten. Außerdem behandle ich Aktualisierungen von Plone.

Anschließend geht es um Performance-Fragen und Techniken zum Auffinden von Schwachstellen. Nachdem Sie diese gefunden haben, beschreibe ich häufig auftretende Probleme. Dann vertiefe ich das Thema Caching als wesentliche Technik dafür, Ihre Plone-Site wirklich schnell und skalierbar zu machen. Wenn es um Performance geht, müssen Sie definitiv wissen, wie Ihr Server mit mehreren Prozessen nach außen skalieren kann und wie man rechenintensive Anfragen behandelt. Dazu benötigen Sie Zope Enterprise Objects (ZEO), was am Ende dieses Kapitels behandelt wird.

Administration einer Plone-Site

Wie sich herausstellt, ist die Administration einer Plone-Site ziemlich einfach: Sie müssen lediglich ein paar Aufgaben erledigen, die für alle Dienste gleich sind. Gemeint ist Folgendes:

  • Sie sollten regelmäßig ein Backup von der Datenbank machen.
  • Sie sollten die Datenbank regelmäßig komprimieren.
  • Sie sollten rotierende Backups der Protokolldateien anlegen.

Diese Aufgaben sollten Sie regelmäßig bei der Wartung Ihrer Website erledigen. In einer Firma haben Sie oftmals standardisierte Werkzeuge für Backups und rotierende Protokolldateien. Diese Werkzeuge lassen sich alle leicht integrieren, da Plone-Daten alle in Form von Dateien im Dateisystem vorliegen.

Backups Ihrer Plone-Site durchführen

Von einer Plone-Site sollten Sie regelmäßig Backups anfertigen. Die meisten Leute erstellen Backups in der Nacht. Ein Backup-Plan sollte aus den Anforderungen Ihrer Anwendung abgeleitet werden. Wenn große Datenmengen geschrieben werden, sind vielleicht häufigere Backups notwendig. Bei einer kleinen Site mit weniger Inhalten mögen weniger häufige Backups, z.B. einmal pro Woche, besser geeignet sein.

Bei einer normalen Plone-Site muss nur von einer Datei ein Backup erstellt werden: von der Zope-Datenbank, in der alle Inhalte der Plone-Site stecken. Diese Datei finden Sie, indem Sie auf das Control Panel im Zope Management Interface (ZMI) zugreifen, dort Database Management wählen und dann auf main klicken. Diese Seite zeigt die Größe und den Ort der Datenbank an. Die Datei heißt Data.fs, und Sie finden sie im Verzeichnis var Ihrer Instanzwurzel. Um das Backup auszuführen, kopieren Sie diese Datei lokal. Dann können Sie sie sicher auf einen externen Speicher kopieren, z.B. auf eine andere Festplatte, einen Server, ein Bandlaufwerk oder was Sie auch immer sonst für ein Backup-System haben. Dieses Backup können Sie sogar dann durchführen, während Plone läuft.

Zum Anlegen von Backups können Sie Ihre eigenen Skripten und Werkzeuge oder ein Werkzeug aus Zope benutzen. Als Beispiel für die erste Möglichkeit zeigt Listing 14.1 ein Linux-Bash-Skript, das ich für das Backup einer Zope-Site benutze.

Listing 14.1. Bash-Skript für ein Backup

#!/bin/bash
# script to copy, gzip, and then copy Zope databases
# to remote server
# make up a filename
fn=`uuidgen`.fs
# copy it locally, you'll want to change the
# path
cp /var/zope.test/var/Data.fs /tmp/$fn
# gzip the file up
gzip /tmp/$fn
# scp over to my backup server and then remove
# the temporary file
# change the destination file
scp /tmp/$fn.gz backup@backups.agmweb.ca:~/Zope
rm /tmp/$fn.gz

Als zweite Möglichkeit steht Ihnen ein Python-Skript namens repozo.py in der Zope-Objektdatenbank (ZODB) zum Erstellen von Backups zur Verfügung. Sie finden dieses Skript online unter http://cvs.zope.org/ZODB3/Tools/repozo.py. Es funktioniert ziemlich gut unter Windows und Linux und kann eine ganze Menge, z.B. vollständige und inkrementelle Backups erstellen und die Datenbank wiederherstellen.

Um mit diesem Skript ein Backup einer Datenbank anzufertigen, müssen Sie zuerst ein Verzeichnis anlegen, das das Backup aufnimmt. In den folgenden Beispielen lautet dieses Verzeichnis /home/backups, aber Sie haben die freie Wahl dabei. Führen Sie Folgendes aus, um ein vollständiges Backup einer Datenbank zu erstellen:

$ python repozo.py -B -F -v -r /home/backups -f /var/zope.test/var/Data.fs
looking for files b/w last full backup and 2003-11-21-18-33-17...
no files found
doing a full backup
writing full backup: 3601549 bytes to /home/backups/2003-11-21-18-33-17.fs

Um ein inkrementelles Backup anzufertigen, lassen Sie einfach die Option -F (für engl. full) weg. Das Skript vergleicht dann die aktuelle ZODB mit dem letzten Backup und kopiert lediglich die Unterschiede. Wenn keine Aktualisierungen stattgefunden haben, erfolgt kein Backup. Folgendes ist ein Beispiel-Backup nach einer Änderung in Plone:

$ python repozo.py -B -v -r /home/backups -f /var/zope.test/var/Data.fs
looking for files b/w last full backup and 2003-11-21-18-39-09...
files needed to recover state as of 2003-11-21-18-39-09:
        /home/backups/2003-11-21-18-33-17.fs
repository state: 3601549 bytes, md5: ab9e46bcdf52641ad6f71db62a9da333
current state   : 3624968 bytes, md5: 73c871bbe2528e152342abea9e25ab27
backed up state : 3601549 bytes, md5: ab9e46bcdf52641ad6f71db62a9da333
doing incremental, starting at: 3601549
writing incremental: 23419 bytes to /home/backups/2003-11-21-18-39-11.deltafs

An diesem Punkt haben Sie ein vollständiges und ein inkrementelles Backup. Dasselbe Skript kann diese Daten nun auch wiederherstellen. Dazu geben Sie die Option -R (für engl. recovery) und mit -o die Ausgabedatei wie folgt an:

$ python repozo.py -R -v -r /home/backups -o /var/zope.test/var/Data.fs
looking for files b/w last full backup and 2003-11-21-18-50-21...
files needed to recover state as of 2003-11-21-18-50-21:
 /home/backups/2003-11-21-18-33-17.fs
 /home/backups/2003-11-21-18-39-11.deltafs
Recovering file to /var/zope.test/var/Data.fs
Recovered 3624968 bytes, md5: 73c871bbe2528e152342abea9e25ab27

Eine vollständige Liste aller Optionen erhalten Sie, wenn Sie repozo.py mit -h ausführen, was alle vorhandenen Optionen ausgibt.

Die Protokolldateien befinden sich standardmäßig im log-Verzeichnis Ihrer Instanzwurzel. Dort gibt es zwei Dateien: eine für Zugriffe und eine für Ereignisse. Den Ort dieser Protokolldatei können Sie in der Konfigurationsdatei angeben, die Sie in Kapitel 2 kennen gelernt haben. In z2.log werden alle ankommenden Anfragen protokolliert und in event.log alle Fehler. Von diesen Dateien sollte regelmäßig ein Backup gemacht werden, zusammen mit eventuell vorhandenen Protokolldateien auf Proxy-Servern, z.B. solchen, die Apache oder IIS (Internet Information Services) produzieren.

Von Code, Templates und eigenen Produkten außerhalb der ZODB sollten Sie ebenfalls regelmäßige Backups anfertigen. Auch dann, wenn Sie diese in einem Versionsverwaltungsprogramm wie CVS (Concurrent Versioning System) aufbewahren, kann es nicht schaden, einen gültigen Schnappschuss Ihrer Installation zu machen.

Wenn Sie Inhalte, andere Datenbanken oder andere Daten haben, die nicht in der ZODB sind, sollten auch diese Teil des Backup-Plans sein, je nachdem, wie oft sie sich ändern. Das könnten Daten in relationalen Datenbanken und Inhalte im Dateisystem sein. All diese Daten werden vom Site-Entwickler erzeugt und kommen in einer normalen "taufrischen" Plone-Site nicht vor. Wenn Sie Zope oder Plone aktualisieren, kann es sinnvoll sein, ein Backup aller beteiligten Dateien zu machen, inklusive Zope und Plone, damit bei einer womöglich fehlerhaften Aktualisierung eine vollständige Wiederherstellung möglich ist.

Die ZODB komprimieren

Die ZODB speichert alle Änderungen an allen Objekten im System. Jedes Mal, wenn sich ein Objekt ändert, wird eine neue Kopie ans Ende der ZODB-Datei angehängt. Dies ist die Datei Data.fs, die ich im vorigen Abschnitt beschrieben habe. Falls die Datenbank große Teilinhalte oder eine große Anzahl von Änderungen enthält, kann das dazu führun, dass die ZODB merklich anwächst.

Eine große ZODB als solche ist kein Problem, auch sie funktioniert einwandfrei, und die Zeiten beim Hochfahren sind vergleichbar (es sei denn, der Index wurde entfernt). Die Zeiten für die Komprimierung werden länger, je größer die Datenbank ist. Daher macht es Sinn, diese alten Kopien von Objekten, die nicht mehr benötigt werden, gelegentlich zu entfernen, um die Datenbank kleiner zu machen. Es ist ganz wesentlich zu wissen, dass Sie beim Komprimieren lediglich Ihre vorhandene Datenbank säubern und einige alte Kopien wegwerfen.

Komprimieren heißt in der Datenbank aufräumen

Eine Komprimierung kann aufwendig sein, und wenn dieser Prozess ausgeführt wird, passiert das in einem separaten Thread, d.h., auch wenn die Geschwindigkeit einer Site dadurch beeinflusst wird, kann sie weiterhin auf Anfragen reagieren. Wie Sie Sites komprimieren, während Plone trotzdem mit maximaler Performance läuft, wird im Abschnitt "ZEO-Clients benutzen" später in diesem Kapitel erklärt. Um eine Komprimierung durchzuführen, gehen Sie ins Control Panel des ZMI, wählen Database Management und klicken auf main.

img/14-01.png

Figure 14.1. Komprimieren einer Datenbank

Geben Sie die Anzahl von Tagen an, für die Sie Objekte behalten möchten, und klicken Sie auf Pack. Wenn Sie z.B. die Anzahl von Tagen auf null setzen (die Voreinstellung), werden alle Versionen der Objekte entfernt. Noch einmal: Nicht das Objekt selbst wird gelöscht, sondern nur diese alten Kopien davon. Eine üblichere Einstellung ist ein Wert um sieben herum, wobei dann Versionen gelöscht werden, die älter als eine Woche sind. Durch die Wahl einer mit Ihrem Backup-Plan verträglichen Einstellung können Sie garantieren, dass Sie von jedem Objekt eine Kopie behalten. Die Komprimierung wird je nach Größe Ihrer ZODB einige Zeit und Verarbeitungskapazität in Anspruch nehmen. Plone läuft währenddessen weiter, wenn auch etwas langsamer, d.h., eventuell möchten Sie ZEO dafür benutzen.

Plone aktualisieren

Plone wird kontinuierlich weiterentwickelt und verbessert, d.h., es kommen ziemlich regelmäßig neue Versionen von Plone heraus. Bevor Sie auf eine neue Version von Plone aktualisieren, sollten Sie aber nachprüfen, ob Sie diese wirklich brauchen. Zwischen den einzelnen Releases gibt es recht häufig nur kleine, möglicherweise wenig relevante Änderungen. Zu jedem Release gibt es eine Liste von Änderungen auf der Seite, wo man es herunterladen kann. Es empfiehlt sich immer ein Blick auf diese Liste, um zu sehen, ob sich die Aktualisierung lohnt.

Machen Sie zuerst ein Backup, und laden Sie dann die Aktualisierung herunter. Am leichtesten führen Sie die Aktualisierung vermutlich durch, indem Sie die gleichen Schritte wie bei der Installation wiederholen. Wenn Sie die Installation mit dem Windows-Installationsprogramm durchgeführt haben, laden Sie das neue Installationsprogramm herunter und wiederholen die Installation. Wenn Sie eine Installation aus den Quellen oder einem Debian-Paket durchgeführt haben, wiederholen Sie diese Schritte. Die Aktualisierung umfasst folgende Schritte:

  1. Die entsprechende Aktualisierung herunterladen
  2. Plone anhalten
  3. Ein Backup durchführen (wie zuvor beschrieben)
  4. Die Aktualisierung installieren
  5. Plone starten

An dieser Stelle möchte ich empfehlen, Plone im Debug-Modus zu starten. Unter Windows können Sie das tun, indem Sie Start - Plone - Plone Debug wählen. Unter Linux machen Sie das mit dem Skript runzope im bin-Verzeichnis Ihrer Instanzwurzel wie folgt:

bin/runzope -X "debug-mode=on"

Durch die Ausführung im Debug-Modus können Sie direkt eventuelle Fehler sehen, die bei der Aktualisierung auf die neue Version aufgetreten sind. Wenn Sie damit zufrieden sind, können Sie mit dem nächsten Schritt, der Migration, weitermachen.

Gehen Sie bei all Ihren Plone-Sites ins ZMI, und greifen Sie auf das Werkzeug portal_migration in Ihrer Plone-Site zu. Es wird ein hellrotes Ausrufezeichen daneben haben, was angibt, das die Site nicht auf dem neusten Stand ist. Nun müssen Sie eine Migration von Plone auf die aktuelle Version vornehmen. Eine Migration ist notwendig, da Sie das Dateisystem aktualisiert haben, aber Ihre Datenbank nicht mit dem Dateisystem synchronisiert ist. Es könnte Änderungen an den Inhaltstypen, den Werkzeugen oder anderen Teilen Ihrer Site geben, die vorgenommen werden müssen.

Die Migration wird versuchen, diese Änderungen für Sie durchzuführen. Solange Sie diese Migration nicht durchführen, könnte es sein, dass Ihre Plone-Site defekt ist. Je nachdem, was bei der Migration gemacht werden muss, kann das einige Zeit brauchen. Befolgen Sie diese Schritte, um eine Migration durchzuführen:

  1. Klicken Sie unter portal_migration auf den Migrate-Reiter.
  2. Klicken Sie auf den Upgrade-Button. Dieser Upgrade-Vorgang kann eine Weile dauern, besonders bei großen Sites oder wenn eine große Aktualisierung notwendig ist.
  3. Das Ergebnis der Migration, eine ziemlich lange Meldung, wird auf dem Bildschirm angezeigt. Die Migration war erfolgreich, wenn die letzte Meldung "End of upgrade path, migration has finished" lautet. Eventuelle Fehlermeldungen werden in Rot hervorgehoben.

Wiederholen Sie diesen Vorgang für alle Plone-Sites in Ihrer Zope-Instanz. Wenn Sie mit der migrierten Site zufrieden sind, halten Sie das im Debug-Modus laufende Plone an. Starten Sie Plone wie üblich neu, und machen Sie ganz normal weiter.

Die Performance von Plone verbessern

Nun haben Sie also eine wunderbare Website, Millionen von Besuchern schauen vorbei, aber sie zeigt nicht ganz die gewünschte Performance. Nun, Plone wurde von vornherein als System entworfen, das reich an Möglichkeiten, aber nicht unbedingt sehr schnell ist, weil die Geschwindigkeit sehr stark von der jeweiligen Anwendung abhängt. Man kann Plone allerdings mit vielen Techniken sehr schnell machen, und es skaliert sehr leicht. In den folgenden Abschnitten behandle ich, wie Sie die langsamen Teile Ihrer Site ausfindig machen, und zeige Ihnen dann Methoden, wie Sie sie verbessern können.

Benchmarks einer Plone-Site erstellen

Bevor Sie versuchen, eine Site zu optimieren, besteht die wesentliche Aufgabe darin, sich einen Zahlenwert für die Performance der Site zu verschaffen. Die Benutzer geben oftmals Feedback der Art "sie ist zu langsam" oder "es braucht zu lange, bis sie geladen wird". Für einen Entwickler sind diese Kommentare nahezu nutzlos. Sie müssen die Geschwindigkeit quantitativ angeben können, um zu wissen, wie schnell die Site jetzt ist und wie schnell sie gemacht werden muss. Erst dann können Sie mit der Optimierung beginnen.

Um einen Benchmark zu erhalten, können Sie ein Werkzeug namens ab bzw. Apache Bench benutzen. Dieses Werkzeug ist Teil des Apache-Servers. Falls Sie Apache 1.3 oder höher unter Linux installiert haben, ist ab bereits enthalten. Unter Windows ist es ab der Version 2 von Apache enthalten. Man kann ab sehr einfach ausführen: Geben Sie einfach die URL (Uniform Resource Locator) an, die Sie testen möchten, z.B. so:

ab http://localhost/

Das Werkzeug ab gibt dann wie folgt zuerst einige Daten über die getestete Site aus:

Benchmarking localhost (be patient).....done
Server Software:        Zope/(unreleased
Server Hostname:        localhost
Server Port:            80
 
Document Path:          /
Document Length:        20594 bytes

Anschließend gibt es wie folgt einige zusammenfassende Statistiken aus:

Concurrency Level:      1
Time taken for tests:   0.771151 seconds
Complete requests:      1
Failed requests:        0
Write errors:           0
Total transferred:      20933 bytes
HTML transferred:       20594 bytes
Requests per second:    1.30 [#/sec] (mean)
Time per request:       771.151 [ms] (mean)
Time per request:       771.151 [ms] (mean, across all concurrent requests)
Transfer rate:          25.94 [Kbytes/sec] received

Das sagt Ihnen, wie lange die Anfrage bearbeitet wurde, wie viele Fehler aufgetreten sind, und wie lang es dauerte, bis eine Anfrage abgearbeitet wurde, was vermutlich die wichtigste Angabe ist. Der nützlichste Wert, den man angeben kann, ist normalerweise Requests per second, d.h. Anfragen pro Sekunde - in diesem Beispiel also 1.30 [#/sec]. Weitere Statistiken, die das Werkzeug ab bietet, geben Informationen darüber an, wie lange es dauert, bis eine Verbindung erstellt wird, wie lange sie bearbeitet wird bzw. wie lange es braucht, bis ein Ergebnis für eine Anfrage vorliegt. Beispiel:

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.0      0       0
Processing:   770  770   0.0    770     770
Waiting:      766  766   0.0    766     766
Total:        770  770   0.0    770     770

Diese letzte Information ist hilfreich und beinhaltet die Zeit für den Aufbau einer Verbindung. Da mein Server auf dem gleichen Rechner wie der Client läuft, ist sie hier ziemlich kurz. Dieser Test zeigt, dass es 1,30 Sekunden dauert, eine Anfrage abzuarbeiten. Der Server wurde dabei natürlich so gut wie gar nicht getestet. Um die reale Welt besser zu simulieren, möchten Sie den Server beim Testen vermutlich mit einigen Anfragen gleichzeitig belasten. Das können Sie tun, indem Sie die Anzahl der Anfragen insgesamt mit der Option -n und die Anzahl der gleichzeitigen Anfragen (Thread) mit -c angeben. Beispiel:

ab -n 20 -c 4 http://localhost/

Hierbei werden insgesamt 20 Anfragen über vier parallele Threads geschickt. Das Endergebnis ist eine leicht andere Anzahl von Anfragen pro Sekunde, nämlich 1.78. Weitere Angaben zu allen verfügbaren Optionen lesen Sie bitte im Handbuch zu Apache Bench unter http://httpd.apache.org/docs/programs/ab.html nach.

Einer der Vorteile von ab besteht darin, dass Sie nicht wirklich die Seiten auf dem Client zusammensetzen. Stattdessen werden sie nur heruntergeladen und dann weggeworfen. Wenn Sie eine Seite mit einer Menge an Skripten oder mit großen Bildern haben, wird die Zeit nicht mitgerechnet, die ein Client braucht, um diese Seite zu etwas zusammenzusetzen, was für den Benutzer Sinn macht. Ein klassisches Beispiel hierfür ist der alte Netscape-Browser, der durch eine große Zahl von Tabellen stark verlangsamt wird oder sogar abstürzen kann. Mit ab wäre das nicht festzustellen, denn es gibt Ihnen eine unabhängigere Zahl, mit der Sie arbeiten können.

Lügen, schlimme Lügen und Benchmark-Zahlen

An dieser Stelle sind Sie vermutlich über diese Zahlen besorgt. Sie scheinen für eine sehr langsame Site zu sprechen. Der Rechner in diesen Beispielen ist mein Toshiba-Laptop mit einem 1,8-GHz-Celeron-Prozessor, 256 Mbyte RAM, Red Hat Linux 9.0 und einer Beta-Version von Plone 2. Außerdem läuft Plone im Debug-Modus gleichzeitig mit KDE, OpenOffice.org, Instant Messenger und mehreren anderen Entwicklerwerkzeugen, inklusive des eigentlichen Benchmark-Werkzeugs. Das heißt, weder ist Plone irgendwie optimiert noch läuft es in einer idealen Umgebung. Ein ähnlicher Test auf einem schnelleren Server ergab einen Wert von etwa 20 Anfragen pro Sekunde.

Der wesentliche Punkt ist, dass Sie mit Hilfe einer objektiven Zahl für die Site-Performance den Erfolg Ihrer Optimierungen messen können. Entwickler können Tricks und Kniffe anwenden und diese testen, um die Zahlen "davor" und "danach" zu vergleichen. Wenn möglich, sollten Sie die Performance-Tests auf einem Rechner durchführen, der möglichst ähnlich zu dem Server in Produktion ist, um vernünftige Zahlen zu erhalten. In diesem Kapitel ist es nicht wichtig, dass die Site X Anfragen pro Sekunde schafft, sondern es ist wichtig, dass eine Änderung eine signifikante Verbesserung der Performance bewirkt.

Denken Sie außerdem daran, dass Zahlen darüber, wie schnell ein bestimmter Teil Ihrer Site ist, für sich allein genommen ziemlich nutzlos sind. Sie müssen verschiedene andere Dinge ebenfalls bedenken, z.B. wie oft die Seite besucht wird, die Erwartungen der Benutzer sowie realistische Anforderungen. Die penibel genaue Messung eines Teils einer Site kann nützlich sein, um ein bestimmtes Problem zu finden, macht Ihre Site aber eventuell kaum schneller. Wie bei den meisten Dingen brauchen Sie auch hier einen vernünftigen Ansatz bei Ihrer Optimierung.

Produktions- vs. Debug-Modus

Eines der Dinge, die am meisten Geschwindigkeit fressen, ist, wenn Sie Plone im Debug-Modus betreiben. Im Debug-Modus werden alle Templates, Skripten und Objekte im Werkzeug portal_skins mit dem Dateisystem verglichen, um zu überprüfen, ob sie aktuell sind. Diese Überprüfung erfolgt bei jeder einzelnen Anfrage, was beim Testen hilfreich ist, aber einen riesigen Performance-Einbruch bedeutet. Auf meinem Testserver z.B. erhöht sich nach dem Abschalten des Debug-Modes die Geschwindigkeit von 1.30 auf 2.41 Anfragen pro Sekunde, eine signifikante Verbesserung.

Um herauszufinden, ob Ihre Site im Debug-Modus läuft, gehen Sie im ZMI zum Objekt portal_migration Ihrer Plone-Site. Am unteren Rand dieser Seite steht eine Liste von Informationen, darunter auch der Status des Debug-Modus. Um ihn zu ändern, ändern Sie die Konfigurationsdatei, wie in Kapitel 2 beschrieben.

Andere Gründe für geringe Performance

Ein Server kann aus verschiedenen Gründen, die nichts mit Plone zu tun haben, langsam laufen. Wenn Sie eine Optimierung durchführen, sollten Sie immer zuerst einen Blick darauf werfen, da Sie hierdurch mit kleinem Aufwand schnell Verbesserungen bei der Geschwindigkeit erreichen können.

Prozessorauslastung

Wenn Sie eine große Anzahl von Anwendungen laufen haben oder nur wenige sehr aufwendige, wird die für Plone verfügbare Prozessorzeit dadurch beschränkt. Das Zusammensetzen von Seiten in Plone kann eine Menge CPU-Zeit in Anspruch nehmen. Eine Anwendung, die durch die verfügbare CPU-Zeit beschränkt ist, heißt auch CPU-beschränkt.

Um herauszufinden, unter welcher Last ein Server unter Linux ist, benutzen Sie den Befehl top. Unter Windows erhalten Sie eine ähnliche Statistik vom Task Manager (den Sie mit der Tastenkombination Strg+Alt+Lösch erreichen). Die empfohlene Geschwindigkeit für Ihre CPU hängt von der Größe und Last des Verkehrs auf Ihrem Plone-Server ab, aber ein 2-GHz-Prozessor ist eine gute Ausgangsbasis.

Größe des Hauptspeichers

Zope benutzt gern einen großen Teil des Hauptspeichers, wenn Objekte aus der ZODB geladen werden. Von allen wesentlichen Eigenschaften eines Zope-Servers hat ein größerer Hauptspeicher vermutlich den größten Effekt. Eine Anwendung, die durch den verfügbaren Hauptspeicher beschränkt ist, heißt auch speicherbeschränkt. Sehr wahrscheinlich wird Ihr Server den Geist aufgeben, wenn er auf diese Grenze stößt, während der Swap-Speicher auf die Festplatte ausgelagert wird.

Um herauszufinden, unter welcher Last ein Server unter Linux ist, benutzen Sie den Befehl top. Unter Windows erhalten Sie eine ähnliche Statistik vom Task Manager (den Sie mit der Tastenkombination Strg+Alt+Lösch erreichen). Die empfohlene Größe des Hauptspeichers hängt von der Größe und Last des Verkehrs auf Ihrem Plone-Server ab, aber 512 Mbyte sind ein guter Anfang. Wenn Sie sich mehr leisten können, empfiehlt sich auch mehr.

An den Hauptspeicherparametern können Sie in Plone etwas drehen, indem Sie die Anzahl der Objekte im Cache erhöhen. Per Voreinstellung hat Plone 400 Objekte im Cache. Das könnten Sie bei einer Site auf 5000 erhöhen, wie in Abbildung 14.2 gezeigt ist. Obwohl sich der Hauptspeicherverbrauch erhöht, steigt dabei aber auch die Performance. Die so gewonnene Performance kann man jedoch unmöglich vorhersagen, weil Objekte naturgemäß unterschiedlich groß sind. Der beste Ansatz ist vermutlich der, diesen Wert heraufzusetzen und dann einige Anfragen zu testen, um zu sehen, ob sich dieser Kompromiss lohnt.

img/14-02.png

Abbildung 14.2. Die Cache-Parameter im Control Panel ändern

Je weniger Threads Zope außerdem benutzt, desto weniger Hauptspeicher wird verbraucht. Zwar ist Zope multithread-fähig, aber meistens wird nur ein Zope-Thread wirklich benutzt. Eine Reduktion der Thread-Anzahl auf drei ergibt einen speichereffizienteren Server. Anstatt zu versuchen, eine große Zahl von Threads laufen zu lassen, wird empfohlen, mit Hilfe von ZEO-Clients mehr Anfragen zu bedienen. Der Abschnitt "Zope Enterprise Objects verwenden" behandelt das etwas detaillierter.

Netzwerkverbindung

Die Netzwerkverbindung kann von entscheidender Bedeutung für die Performance einer Anwendung sein. Sie können nicht schneller sein als die langsamste Verbindung zwischen Ihnen und dem Client. Beachten Sie beim Optimieren einer Plone-Site daher auch die Verbindungszeit. Wenn eine Verbindung zwei Sekunden braucht, ist die Optimierung des Codes ziemlich sinnlos.

Auch hierbei kann das Werkzeug ab helfen. Wenn Sie einen Benchmark-Test von Plone.org von Britisch-Kolumbien, Kanada, aus durchführen (der Server befindet sich in Texas), können Sie in der folgenden Ausgabe sehen, dass der Median der Wartezeit für Verbindungen über das Netzwerk 125 Millisekunden betrug:

            Connection Times (ms)
            min  mean[+/-sd] median   max
Connect:       90  133  40.2    125     211
Processing:   511 1103 400.2   1113    1846
Waiting:      202  310 110.3    293     565
Total:        601 1236 411.2   1211    2043

Eventuell hat der Server auch eine Beschränkung bezüglich der Anzahl der Verbindungen oder bei der Reise durch interne Firewalls. Wenn ein Prozess derart durch die Zeit beschränkt ist, die er für eine Input/Output-Operation benötigt (I/O), heißt er auch I/O-beschränkt. Was Sie an dieser Stelle machen können, hängt davon ab, über welche Möglichkeiten Sie im Netzwerk verfügen. Wenn Ihr Client sehr weit von Ihrem Server entfernt ist und die Verbindung sehr langsam ist, dann könnten Caches in der Nähe des Clients eine geeignete Möglichkeit sein.

Ihre Anwendung

Es könnte natürlich auch sein, dass Ihre Anwendung Ursache für die geringe Performance ist. Es gibt zahlreiche (und vermutlich übertriebene) Beispiele von Dienstleistungsfirmen für Kunden mit Problemen. Zu den bekannteren Beispielen gehören die folgenden:

  • Kopierter Code von einer Website, der einen tief im System verborgenen sleep-Aufruf enthielt, wodurch das Skript einige Sekunden pausiert. Eine von jemandem durchgeführte Code-Inspektion hat das zu Tage gebracht, und die Zeile wurde entfernt.
  • Mehrfache Abfragen in relationalen Datenbanken, z.B. über ein Dutzend auf einer Seite. Mit einem intelligenteren Design wurden die Abfragen kombiniert, was auch ein Caching erlaubte.
  • Ein Skript, das Informationen aus der ZODB herausholte, indem alle Objekte in der Datenbank aufgeweckt wurden. Durch die Benutzung des Katalogs (siehe Kapitel 10) wurde die Performance viel besser.
  • Eine Abfrage, die alle Datensätze einer Datenbank holt, dann aber nur jeweils 100 auf einer Seite anzeigt und die anderen 99900 wegwirft. Das wurde mit effizienteren SQL-Anweisungen gelöst.

Bevor Sie voreilige Schlussfolgerungen über die Ursache des Problems ziehen, lohnt es sich, Laufzeitmessungen auf der Site vorzunehmen, um festzustellen, wo das Nadelöhr liegt.

Laufzeitmessungen mit Plone

Da Sie die Zeit, die zum Erzeugen von Seiten benötigt wird, quantitativ bestimmen können, können Sie nun versuchen zu optimieren. Das erste Problem besteht allerdings darin, die zu optimierende Stelle zu finden. Wie in früheren Kapiteln gezeigt wurde, ist die Hauptseite eine Sammlung von Templates, Skripten und anderem Code, der zusammengesetzt wird, um eine Seite zu erstellen. Wo sollte ein Entwickler in diesem Berg von Code nachschauen? Um bei der Suche nach Performance-Schwachstellen zu helfen, können Sie so genannte Profiler für Laufzeitmessungen von Aufrufen, Page Templates und Python selbst benutzen. Jeder dieser Profiler kümmert sich um ein Element der Site und berichtet, wie viel Zeit beim Erstellen der Seite und bei jeder dieser drei Komponenten verbraucht wurde.

Beachten Sie bitte, dass Sie beim Aktivieren aller drei Werkzeuge feststellen werden, dass Ihre Plone-Site wirklich langsam wird (und zwar um eine signifikante Größenordnung). Jedes dieser Werkzeuge bringt einen Verlust an Performance mit sich. Sie sollten deren Installation immer rückgängig machen oder sie deaktivieren, nachdem Sie sie benutzt haben, um sicherzugehen, dass Ihre Site mit maximaler Effizienz läuft. Außerdem gilt beim gleichzeitigen Einsatz aller Profiler, dass Sie dann auch die Laufzeit dieser Profiler mitmessen, was dann wirklich verwirrend wird. Ich empfehle Ihnen, mit dem Aufruf-Profiler zu beginnen. Schalten Sie dann so lange jeweils einen der anderen Profiler ein, nachdem Sie den vorherigen deaktiviert haben, bis Sie genügend Informationen haben.

Call Profiler

Dieses Zope-Produkt nimmt eine Anfrage, z.B. nach der Hauptseite, und gibt an, welche Objekte bei ihrer Abarbeitung benutzt wurden und wie viel Zeit jedes davon benötigt hat. Den Call Profiler finden Sie unter http://zope.org/Members/richard/CallProfiler. Trotz der Kommentare auf der Seite ist das Produkt nicht in Zope 2.6 integriert. Installieren Sie das Produkt auf die übliche Weise, und starten Sie dann Ihr Zope neu.

Um den Call Profiler zu aktivieren, gehen Sie im ZMI zum Control Panel und wählen Call Profiler. Das Produkt funktioniert derart, dass es Hooks in ein Objekt installiert, damit beim Zugriff auf das Objekt die Zeit für die Wiedergabe des Objekts gemessen werden kann. Das heißt, dass Call Profiler nur bei den Objekten aktiviert wird, die Sie überwachen möchten, wie in Abbildung 14.3 zu sehen ist. Bei einer normalen Plone-Installation müssen Sie das Filesystem Script (Python)- und das Filesystem-Page Template überwachen. Der Call Profiler merkt sich diese Einstellungen nicht nach einem Neustart von Zope, d.h., dass bei einem einfachen Neustart die Hooks deaktiviert werden und Sie bereit für die Auslieferung sind.

img/14-03.png

Figure 14.3. Call Profiler mit ausgewählten Dateisystem-Hooks

Nachdem die zu überwachenden Objekte ausgewählt wurden, greifen Sie auf die gewünschte URL zu. Am einfachsten greift man auf die zu testende URL zu, indem man das zuvor erwähnte Werkzeug ab ausführt, aber einen Webbrowser zu benutzen funktioniert genauso gut. Wenn Sie in diesem Fall die Hauptseite auf localhost messen, starten Sie Folgendes:

ab -n 20 -c 4 http://localhost/

Hierdurch werden 20 Anfragen an Plone gesendet. Sobald sie abgearbeitet sind, können Sie auf die Messungen dieser Anfragen zugreifen. Zurück in der Schnittstelle von Call Profiler sehen Sie oben drei Reiter: Results, Results by URL und Aggregates. Da mehrere Anfragen ausgeführt wurden, wählen Sie den Aggregates-Reiter, der am leichtesten zu verstehen ist. In der Liste der aufgerufenen Seiten wird die getestete URL sein. Klicken Sie auf diesen Link, um die Ergebnisse zu dieser URL zu sehen. Nun sollten Sie etwas wie in Abbildung 14.4 sehen.

img/14-04.png

Abbildung 14.4. Ergebnisse der Laufzeitmessung

In diesem Beispiel sehen Sie die Elemente, die der Call Profiler erkennen kann. Leider sind die Ergebnisse manchmal etwas kompliziert zu entziffern. Auf den ersten Blick addieren sich die Ergebnisse zu mehr als 100 %. In diesem Fall nimmt document_view 71,1 % der verbrauchten Zeit ein. Das ist allerdings irreführend, weil sich die Werte unter dieser Abbildung auf document_view und nicht auf die ganze Seite beziehen. In diesem Beispiel für die gesamte Seite nimmt alles vor browserDefault 19,9 % der Anfrage in Anspruch. Dann geht sie zu document_view über, wofür Sie auch den Prozentanteil sehen können. In diesem Fall macht der Übergang von toLocalizedTime nach getPreviousMonth 23,3 % der Zeit zur Darstellung von document_view aus.

Page Template Profiler

Der Page Template Profiler funktioniert nur mit dem Page Templates-System von Zope. Ähnlich wie der Call Profiler gibt er an, wie viel Zeit bei jedem Aufruf in einem Page Template verbraucht wird. Da Sie im vorigen Beispiel gesehen haben, dass die meiste Zeit in einem Page Template verbraucht wird (document_view), finden Sie es vermutlich interessant zu wissen, wo die Zeit in diesem Template genau verbraucht wird.

Den Page Template Profiler finden Sie unter http://zope.org/Members/guido_w/PTProfiler. Installieren Sie das Produkt, und starten Sie dann Zope neu. Um die Installation rückgängig zu machen, müssen Sie den Page Template Profiler aus Ihrem Products-Verzeichnis entfernen, wenn Sie mit der Messung fertig sind.

Gehen Sie nach der Installation im ZMI zur Zope-Wurzel, und wählen Sie PT Profile Viewer im Dropdown-Menü Add. Füllen Sie das Erstellen-Formular aus, indem Sie als ID einen eindeutigen Wert eingeben (geben Sie z.B. PTProfiler ein), und klicken Sie dann auf Add. Wiederholen Sie nun den Aufruf der zu messenden Seite, indem Sie das Werkzeug ab starten oder in einem Browser auf die Seite zugreifen. Greifen Sie auf das gerade hinzugefügte Page Template Profiler-Objekt zu, und Sie werden ein Ergebnis für die gerade ausgeführte Anfrage sehen. Klicken Sie darauf, um weitere Details zu sehen (vergleiche Abbildung 14.5).

img/14-05.png

Abbildung 14.5. Ergebnisse des Page Template Profilers

In diesem Fall sehen Sie, dass auf meiner Site calendarBox jedes Mal 0,7321 Sekunden benötigt, wenn es aufgerufen wird. Da die gesamte Seite 1,9 Sekunden benötigt, können Sie davon ausgehen, dass dies ein Bereich ist, den ich optimieren könnte.

Python Profiler

Der Python Profiler bietet sehr fein aufgelöste Messwerte und wird normalerweise bei der komplexeren Fehlersuche im darunter liegenden Code verwendet. Er liefert einen detaillierten Bericht der Zeiten, die in verschiedenen Bereichen des Python-Code verbracht werden. Bei den Messungen einer Site würden Sie so etwas normalerweise nicht benutzen. Aber der Vollständigkeit halber möchte ich es in diesem Abschnitt beschreiben.

Um den Python Profiler zu aktivieren, müssen Sie eine Variable zur Konfigurationsdatei hinzufügen. Schalten Sie in der Datei zope.conf Ihres etc-Verzeichnisses den Befehl publisher-profile-file ein. Dazu definieren Sie eine Datei, in die er schreiben wird. Unter Windows könnte das C:\zope.output sein, unter Linux ist es /tmp/zope.output. Fügen Sie die folgende Zeile unter Linux hinzu:

publisher-profile-file /tmp/zope.output

Dann starten Sie Plone neu, das dann sehr langsam laufen wird. Wenn Sie eine große Anzahl von Anfragen abarbeiten und die Ergebnisse untersuchen möchten, dann enthält die in der Umgebungsvariable angegebene Datei die Ausgabe der Daten. Rufen Sie, wie in den vorherigen Beispielen, die zu messende Seite mit dem Werkzeug ab oder einem Webbrowser auf. Dann gehen Sie im ZMI zum Control Panel, wählen Debug Info und wählen dann den Profiling-Reiter. Sie erhalten dann eine Ausgabe des Python Profilers, wie sie in Abbildung 14.6 zu sehen ist.

img/14-06.png

Abbildung 14.6. Ergebnisse des Python Profilers

Wie Sie in Abbildung 14.6 sehen können, zeigt die Ausgabe Details von allem, was Zeit verbraucht. Ich musste das nur selten benutzen.

Einfache Optimierungstricks

Nach einem sehr detaillierten Blick auf Plone hat das Plone-Entwicklerteam die folgenden Optimierungstricks gefunden.

Die Namenssuche einschränken

Die übertriebene Suche nach Namen ist ein häufiger Fehler, dessen Lösung in der Definition einer lokalen Variable besteht. Im folgenden Beispiel muss Plone bei jeder Wiederholung der Schleife eine Suche nach portal_url durchführen:

<tal:block
 tal:repeat="result here/portal_catalog">
   <a href=""
      tal:attributes="href here/portal_url/getPortalUrl">Home</a>
   ...
</tal:block>

Dabei wäre es schneller, ein tal:define wie folgt zu benutzen:

<tal:block
 tal:repeat="result here/portal_catalog"
 tal:define="url here/portal_url/getPortalUrl>
    <a href=""
       tal:attributes="href url">Home</a>
       ...
</tal:block>

Wie schon gesagt, Plone bietet eine große Zahl von globalen Defines. Durch die Verwendung dieser Definitionen kann ein Entwickler die Anzahl der Traversierungen reduzieren. Eine vollständige Liste all dieser Defines finden Sie in Anhang A.

Sicherheitsüberprüfungen und Traversierung

Immer, wenn auf ein Objekt, ein Objektattribut oder eine Methode eines Objekts zugegriffen wird, wird eine Sicherheitsüberprüfung durchgeführt. Auch, wenn jede einzelne nicht so kostspielig ist, können sich viele Sicherheitsüberprüfungen schnell aufaddieren.

Das gilt besonders dann, wenn Sie ein Objekt traversieren, z.B. in here/ordnerA/ordnerB/objekt. In diesem Fall führt Zope Sicherheitsüberprüfungen auf allen einzelnen Ordnern und dann auf dem Objekt durch. Wenn auf die Information jedes Mal ohne diese Traversierung zugegriffen werden kann, werden Sie einen Performance-Gewinn feststellen. Eine andere Methode, Sicherheitsüberprüfungen zu vermeiden, besteht darin, Code im Dateisystem unter Products zu schreiben. Der Code unter Products wird als vertrauenswürdiger Code betrachtet, wird weniger geprüft und daher schneller ausgeführt.

Der ZCatalog

Der ZCatalog ist ein effizienter Binärbaum mit Daten über Objekte. Sie sollten ihn (in den meisten Situationen) dann benutzen, wenn Sie eine Liste von Objekten erstellen, z.B. Suchergebnisse, bei Zusammenfassungen, beim Finden von Objekten usw. Wenn der Katalog eine Reihe von Ergebnissen zurückgibt, die auf eine Liste von leichtgewichtigen Objekten (so genannten Brains) zugreifen, findet beim Zugriff auf diese Brains weder eine Traversierung noch eine Sicherheitsüberprüfung auf dem Objekt statt.

Zu viele Features

Das mag offensichtlich erscheinen, aber Plone wird mit einer Menge von Features ausgeliefert, die Sie nicht unbedingt benötigen. So benötigen z.B. sowohl das Kalender- als auch das Navigations-Portlet beide große Ressourcen, haben aber einen allgemein eher beschränkten Nutzen. Wenn Sie diese Features nicht benötigen und sie abschalten, steigt dadurch die Performance.

Lohnt sich die Optimierung?

Bevor Sie irgendeine Optimierung durchführen, sollten Sie eine einfache Kosten/Nutzen-Analyse erstellen, um zu sehen, ob es sich lohnt, die Optimierung vorzunehmen.

Angenommen, Sie haben z.B. eine Seite, die in 0,5 Sekunden erstellt wird. Auf dieser Seite verbraucht ein Skript 10 % dieser Zeit. Wenn Sie dieses eine Skript doppelt so schnell ausführen können, gewinnen Sie dadurch 0,025 Sekunden bei dieser Seite. In diesem Fall ist der Nutzen einer solchen Optimierung gering, weil es einige fixe Kosten gibt, z.B. die eines Entwicklers, der die Analyse durchführt, die Kosten beim Testen dieser Optimierung und möglicherweise die einer Änderung der Dokumentation.

Diese Arbeiten durchzuführen bedeutet auch ein substanzielles Risiko. Beim Ändern von Code können neue Fehler in der Anwendung entstehen. Mit Hilfe von Methoden wie agiler Programmierung könnten diese aber minimiert werden. Außerdem schafft es ein Programmierer vielleicht nicht, die Anwendung schneller zu machen, oder macht sie sogar langsamer.

Es gibt auch Alternativen zur Optimierung des Codes, z.B. könnten Sie mehr Hauptspeicher oder Hardware installieren, falls die Anwendung durch einen dieser Faktoren beschränkt wird. Auch wenn viele Programmierer der Meinung sind, dass es faul ist, Probleme durch mehr Hardware zu lösen, kann das eine sehr kostengünstige Lösung sein. Neue Hardware stellt ein geringes Risiko dar, kann einen hohen Geschwindigkeitszuwachs bringen und kostet oftmals weniger als ein Programmierer.

Außerdem können Sie Ihren Server wirklich durch Caching oder das Hinzufügen weiterer Rechner skalieren, auf die Sie die Last verteilen. Diese Techniken werden im Rest dieses Kapitels behandelt.

Inhalte cachen

Nun, da Sie die langsamen Teile Ihrer Anwendung gefunden haben, werden Sie das wichtigste Werkzeug zur Steigerung der Performance kennen lernen: das Caching. Unter Caching versteht man die Zwischenspeicherung von Daten, die wieder benutzt werden sollen, ohne sie neu zu berechnen. Es gibt viele, viele Arten von Cache-Speichern und sie können auf vielerlei Weisen benutzt werden.

Mit dem Begriff Caching meine ich zwei Dinge, die man cachen kann: Inhalte und Skins. Inhalte sind Daten, die der Benutzer in Inhaltstypen eingegeben hat. Skins beziehen sich auf alles in portal_skins und können Templates, Skripten, Bilder oder Dateien sein. Diese zwei Dinge werden im Cache unterschiedlich gespeichert.

Ich denke beim Caching gern in Begriffen, die mit dem Grad an Einflussmöglichkeit zu tun haben, die ich über den Caching-Mechanismus habe. Mit anderen Worten: Je näher das Caching beim Client durchgeführt wird, desto schneller wird die Antwort sein, aber desto weniger Einfluss habe ich auch auf diesen Cache. Das beinhaltet auch die Möglichkeit, dass es überhaupt keinen Cache-Speicher gibt. Abbildung 14.7 illustriert das Caching zwischen einem Client und einem Server.

img/14-07.png

Abbildung 14.7. Cache-Speicher zwischen einem Client und einem Server

Der Browser-Cache des Benutzers ist der schnellste Platz, an dem man etwas cachen kann, aber Sie können nicht wissen, ob ein Benutzer in seinem Browser das Caching überhaupt eingeschaltet hat. Danach kommen die zwischengelagerten Cache-Speicher von Proxy-Servern. Denken Sie daran, dass das Ihr Proxy-Server sein könnte (der unter Ihrer Kontrolle sein sollte) oder der Proxy eines Internet Service Providers (ISP). Und schließlich gibt es die Möglichkeit von Cache-Speichern auf dem Server.

In den folgenden Abschnitten erörtere ich die folgenden Caching-Mechanismen:

  • Caching von Skin-Elementen mit dem Accelerated HTTP Cache Manager
  • Caching von Code mit dem RAM Cache Manager
  • Caching von benutzererstellten Inhalten mit dem Caching Policy Manager

Dann werde ich erläutern, wie man Apache und Squid benutzt, zwei gern verwendete externe Server, die über eine Menge an Konfigurationsoptionen für eine hohe Performance verfügen.

Skins cachen

Im Hypertext Transfer Protocol (HTTP) können Sie HTTP-Header für das Caching setzen. Wenn eine Antwort mit solchen Headern zurückgegeben wird, ist es die Aufgabe der Proxies zwischen dem Client und dem Server, das Objekt gemäß dieser Header zu cachen. In Abbildung 14.7 könnte das ein beliebiger Cache-Speicher ab dem Server-Cache oder darunter sein. Dieser Proxy kann ein Webserver sein, über den Sie auf dem Server verfügen, z.B. Apache, oder ein Proxy im Einflussbereich des ISPs. Wie ich noch zeigen werde, ergibt das ein mächtiges Werkzeug, wenn es mit Apache oder Squid kombiniert wird.

Zu diesem Caching kann auch der Browser beitragen, wenn er so eingestellt ist, dass er Caching verwendet (beim Internet Explorer ist das standardmäßig der Fall). Wenn ein Browser allerdings eine Seite aktualisiert, sendet er den Header Pragma: no-cache, was auch die Proxies zwingt, ihre Kopie erneut zu laden.

Diese Art von Caching betrifft die gesamte Antwort, d.h., es kann riskant sein, wenn Sie versuchen, das auf eine ganze Seite anzuwenden. Am meisten wird das mit Bildern, Stylesheets, JavaScript oder Seiten benutzt, die sich nicht oft verändern. Bilder, die auf Ihren Seiten oft wiederholt werden, um hübsche Elemente zu erzeugen, z.B. abgerundete Ecken oder Hintergrundbilder, sind hierfür ideal.

Plone erzeugt standardmäßig einen Accelerated HTTP Cache Manager namens HTTPCache in der Wurzel Ihrer Plone-Site. Beim Zugriff auf dieses Objekt über das ZMI erscheinen die Management-Optionen für den Cache-Speicher. Das Folgende sind alles vernünftige Voreinstellungen, und zu Beginn muss nichts verändert werden:

  • Title: Der Titel des Cache Managers, optional.
  • Interval: Die Zeit (in Sekunden), die das Objekt im Cache bleibt.
  • Cache anonymous connections only: Hiermit wird nur bei anonymen Benutzern gecacht.
  • Notify URLs: Das sind URLs von Proxies zum Herunterladen, die geleert werden müssen, wenn sich das Objekt verändert. Weitere Details dazu finden Sie im Abschnitt "Squid verwenden".

Um zu sehen, wie der Accelerated HTTP Cache Manager funktioniert, basiert das folgende Beispiel auf einem Testobjekt, einem Bild namens test.gif. Um zu sehen, welche Header zurückgegeben werden, müssen Sie diese Header testen. Dazu können Sie ein einfaches Python-Skript namens header.py benutzen. Dieses Skript finden Sie in Anhang B. Unter Linux macht das Programm wget das Gleiche, wenn Sie die Option -S angeben, obwohl es die Datei immer noch für Sie herunterlädt. Beispiel:

wget -S http://www.agmweb.ca

Es folgen zuerst einmal die Header, die für test.gif zurückgegeben werden, bevor Sie das zum Cache-Manager hinzugefügt haben:

[andy@basil scripts]$ ./header.py http://localhost:8080/test.gif GET
Accept-Ranges: bytes
Connection: close
Content-Length: 2541
Content-Type: image/gif
Date: Wed, 03 Sep 2003 23:55:38 GMT
Etag:
Last-Modified: Wed, 03 Sep 2003 23:54:27 GMT
Server: Zope/(unreleased version, python 2.2.2, linux2) ZServer/1.1

Nach dem Hinzufügen des Bildes zum Cache prüfen Sie die HTTP-Header mit dem Skript erneut. Sie werden zwei neue Header finden. Beispiel:

[andy@basil scripts]$ ./header.py http://localhost:8080/test.gif GET
...
Cache-Control: max-age=3600
Expires: Thu, 04 Sep 2003 00:56:03 GMT on 2.2.2, linux2) Zserver/1.1

Hinweis

Leider hält sich Zope 2 nicht an das RFC (Request for Comments) für HEAD-Anfragen. Anstatt bei einer HEAD-Anfrage den vollen Satz an Headern zu schicken, fehlen die Werte vom Cache Manager. Beim Testen sollten Sie immer GET-Anfragen schicken.

Weitere Informationen zu den HTTP-Headern und den Zusammenhang mit dem Caching finden Sie im RFC 2616 unter http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html.

Der Accelerated HTTP Cache Manager speichert eine ganze Antwort im Cache, was mit statischen Elementen gut funktioniert. Eine normale Plone-Seite besteht aber aus personalisierten Elementen, z.B. dem Kalender, der persönlichen Navigationsleiste usw. In dieser Situation müssen Sie nur einen Teil einer Seite cachen können, und hier kommt der RAM Cache Manager ins Spiel.

Der RAM Cache Manager speichert die Ausgabe eines Objekts im RAM, d.h., dass es beim nächsten Auftreten dieses Skripts aus dem Cache geholt wird. Wiederholte Aufrufe dieses Objekts führen dazu, dass die Ausgabe so lange aus dem Cache geholt wird, bis der Cache abläuft. Der springende Punkt bei diesem Manager ist der, dass Sie es vermeiden, jedes Mal komplizierte oder umfangreiche Berechnungen durchzuführen. Stattdessen speichern Sie das Ergebnis und benutzen es erneut. Dieser Cache Manager speichert keine Bilder oder Dateien. Er hält die Benutzer nicht vom Versuch ab, den Cache dahingehend zu konfigurieren, aber er hat keinen Effekt auf diese Objekte.

Plone erstellt standardmäßig einen RAM Manager namens RAMCache in der Wurzel Ihrer Plone-Site. Beim Zugriff auf dieses Objekt über das ZMI werden die Management-Optionen für den Cache aufgerufen. Die folgenden Standardwerte sind alle vernünftig, und zu Beginn muss nichts geändert werden:

  • Title: Der Titel des Cache Managers, optional.
  • REQUEST variables: Variablen, die die Cache-Bedingung ausmachen. Das ist eine mächtige Option, die die Bedingungen für das Zwischenspeichern von Benutzervariablen darstellt. Wenn z.B. ein zu cachendes Element verlangt, dass es für jeden Benutzer anders oder in verschiedenen Sprachen gecacht werden soll, können Sie hier die REQUEST-Variablen angeben, die Sie cachen möchten.
  • Threshold entries: Die maximale Anzahl von Einträgen, die im Cache gespeichert werden kann. Verringern Sie diesen Wert, wenn der Cache zu viel RAM verbraucht.
  • Maximum age of a cache entry: Die Zeit (in Sekunden), die das Objekt im Cache bleibt.
  • Cleanup interval: Gibt an, wie oft der Cache gesäubert wird.

Da die Anfragen nach dem Objekt bis zu Zope durchkommen, reduziert sich der Netzwerkverkehr dadurch keineswegs. Zope stellt das Ergebnis lediglich schneller dar. Nach der Wahl des Statistics-Reiters im ZMI wird eine Statistik über die genaue vom Cache zurückgegebene Trefferanzahl ausgegeben und darüber, wie viele Zugriffe an das Objekt weitergegeben wurden. Wenn zu viele Zugriffe ans Objekt weitergereicht werden, möchten Sie eventuell die Cache-Konfiguration ändern und weniger REQUEST-Variablen angeben oder die Verweilzeit im Cache erhöhen.

Caches zuweisen

Um ein Objekt im Dateisystem zum Cache hinzuzufügen, geben Sie einfach für dieses Objekt den Namen des Caches in der .metadata-Datei an (.metadata-Dateien wurden in Kapitel 7 erläutert). Plone macht das schon für eine Reihe von Bildern, bei CSS und JavaScript. Die Datei plone_skins /plone_images/pdf_icon.gif.metadata lautet z.B. wie folgt:

[default]
title=Pdf icon
cache=HTTPCache

Das bedeutet, dass das Bild mit HTTPCache gecacht wird. Die meisten Objekte im Dateisystem eignen sich mehr für den HTTPCache als für den RAMCache.

Inhaltstypen cachen

Das Cachen von Inhaltstypen ist ein wenig schwieriger und verlangt den Einsatz des Caching Policy Managers. Plone installiert dieses Werkzeug standardmäßig, und Sie finden es in der Wurzel der Plone-Instanz unter der ID caching_policy_manager.

Bevor Sie irgendeinen Inhalt cachen können, müssen Sie die Cache-Einstellungen für die Templates in Plone ändern. Per Voreinstellung gibt Plone Header für Inhalte aus, die das Caching völlig ausschalten. Wenn Sie Folgendes nicht machen, funktioniert der Rest dieses Abschnitts nicht. Wenn Sie portal_skins und dann plone_templates anklicken, finden Sie das Page Template global_cache_settings. Es wird auf allen Seiten benutzt, die das Plone-Haupt-Template benutzen. Dieses Template sieht zurzeit wie folgt aus:

<metal:cacheheaders define-macro="cacheheaders">
    <metal:block tal:define="dummy python:request.RESPONSE.setHeader 
'Content-Type', 'text/html;;charset=%s' % charset)" />
    <metal:block tal:define="dummy python:request.RESPONSE.setHeader 
('Content-Language', lang)" />
    <metal:block tal:define="dummy python:request.RESPONSE.setHeader 
('Expires', 'Sat, 1 Jan 2000 00:00:00 GMT')" />
    <metal:block tal:define="dummy python:request.RESPONSE.setHeader 
('Pragma', 'no-cache')" />
</metal:cacheheaders>

Das bedeutet, das nichts gecacht wird, weil die HTTP-Header Pragma: no-cache und Expires gesetzt wurden. Um das auszuschalten und um sicherzustellen, dass Sie etwas Bestimmtes cachen können, passen Sie dieses Template an und entfernen die Direktiven Pragma und Expires. Ihr Template sollte nun wie folgt aussehen:

<metal:cacheheaders define-macro="cacheheaders">
    <metal:block tal:define="dummy python:request.RESPONSE.setHeader 
'Content-Type', 'text/html;;charset=%s' % charset)" />
    <metal:block tal:define="dummy python:request.RESPONSE.setHeader 
('Content-Language', lang)" />
</metal:cacheheaders>

Nach diesem Schritt können Sie weiterhin bestimmte Dinge mit dem caching_policy_manager gezielt cachen. Gehen Sie im ZMI zu diesem Werkzeug, und Sie werden die folgenden Optionen sehen:

  • Policy ID: Eine eindeutige ID für eine Policy, wird nur intern benutzt.
  • Predicate: Ein TALES-Ausdruck zum Filtern der Inhalte. Die Variable content enthält das gerade dargestellte Objekt.
  • Mod. Time: Ein TALES-Ausdruck, der ausgewertet wird und einen Wert aus dem Objekt für die Berechnung des Änderungszeitpunkts zurückgibt. Die Variable content ist das gerade dargestellte Objekt.
  • Max age (secs): Gibt an, wie lange der Cache-Header dafür gesetzt werden soll.
  • Vary: Variiert den zu sendenden Header (mehr darüber erfahren Sie später im Abschnitt "Squid verwenden").
  • No-cache: Sendet den HTTP-Header no-cache.
  • No-store: Sendet den HTTP-Header no-store.
  • Must-revalidate: Sendet den HTTP-Header must-revalidate.

Das Folgende ist eine Beispiel-Policy, die alle Bilder auf der Site cachen würde:

  • Policy ID: Images
  • Predicate: python:content.portal_type=='Image'
  • Max age (secs): 3600

Lassen Sie alle anderen Felder leer, und wählen Sie Add, um diese Policy hinzuzufügen. Der caching_policy_manager sieht nun ungefähr wie in Abbildung 14.8 aus.

img/14-08.png

Abbildung 14.8. Der caching_policy_manager mit hinzugefügter Bilder-Policy

Um das richtig zu testen, müssen Sie über die Plone-Schnittstelle ein Bild zu Ihrer Site hinzufügen. Die Bilder werden mit den passenden Headern gesendet, wenn Sie die Aktion Anzeigen des Objekts aufrufen. Ich hoffe, dass man diese Aktion in späteren Versionen dieses Werkzeugs konfigurieren kann. Sie werden das mit test.gif testen, einem Bild, das von einem Site-Mitglied über die Plone-Schnittstelle hinzugefügt wurde, und zwar wie folgt:

~/header.py http://localhost/test.gif/view GET
Cache-Control: max-age=3600
Connection: close
Content-Language:
Content-Length: 19810
Content-Type: text/html;charset=utf-8
Date: Fri, 05 Sep 2003 18:42:44 GMT
Etag:
Expires: Fri, 05 Sep 2003 19:42:44 GMT
Last-Modified: Fri, 05 Sep 2003 18:33:41 GMT
Pragma: no-cache
Server: Zope/(unreleased version, python 2.2.2, linux2) ZServer/1.1

Wie erwartet werden nun die Header Last-Modified und Expires gesendet. Durch die Änderung von Prädikaten und das Hinzufügen mehrerer Policies können Sie ein recht ausgefeiltes Caching-System erstellen. Kompliziertere Regeln können Sie natürlich an ein Script (Python)-Objekt abgeben, wenn Sie das wünschen. Wenn das Prädikat z.B. wie folgt lautet:

python: here.myCachingRules(content)

dann fügen Sie ein Script (Python)-Objekt namens myCachingRules hinzu, um diese Regeln zu berechnen. Beispiel:

##parameters=content
# cache all files, images and anything
# thats published
if content.portal_type in ['File', 'Image']:
    return 1
if content.review_state in ['published',]:
    return 1

In diesem Skript cachen Sie alle Dateien und Bilder sowie alles, was im Zustand Veröffentlicht ist, indem Sie die HTTP-Header über den Caching Policy Manager setzen.

Beispiel: Caching auf ZopeZen.org

Bei der Entwicklung der Site http://www.zopezen.org gab es ein Hauptproblem. Die Erstellung der Hauptseite von ZopeZen, auf der die Nachrichten und die Anzahl der Antworten aufgelistet sind, ist sehr aufwendig. In Plone gibt es keinen einfachen Weg, um aus dem Katalog die Anzahl der Diskussionsbeiträge zu einem Element zu berechnen.

Das ist eine ideale Situation für den RAM Cache Manager. Da der Verkehr durch neue Elemente oder Nachrichten ziemlich gering ist (vielleicht ein oder zwei pro Tag), erscheint die Annahme vernünftig, dass sich die Hauptseite während einer Zeitdauer von 30 Minuten nicht stark verändert. Die Funktion, die die Nachrichten und Antworten holt, heißt getNewsAndReplies, und sie erledigt die Aufgabe, alle für das Template index_html benötigte Daten zu holen.

Das Template index_html verfügt über benutzerspezifische Elemente. Der Anmeldekasten links zeigt z.B. den Benutzern, welche Optionen sie haben. Das heißt, dass es nicht funktionieren würde, einen Accelerated HTTP Cache Manager zu benutzen oder das ganze Template mit dem RAM Cache Manager zu cachen. Das würde dazu führen, dass die Benutzer die Optionen anderer Benutzer sehen könnten.

Die ZopeZen-Skin cacht stattdessen das Script (Python)-Objekt getNewsAndReplies, indem sie dieses zum RAM Cache Manager hinzufügt. Dadurch wird garantiert, dass der Großteil der aufwendigen Arbeit der Seitendarstellung gecacht wird. Da die einzelnen Nachrichten für alle Benutzer gleich sind, macht ein Cachen auf Basis der REQUEST-Variablen keinen Sinn. Daher wurde AUTHENTICATED_USER aus der Liste der REQUEST-Variablen für den Cache entfernt. Eine Laufzeitmessung auf der Hauptseite ergibt ohne Cache 1,06 Anfragen pro Sekunde, während mit Cache 4,96 Anfragen pro Sekunde bearbeitet werden, das ist ein signifikanter Unterschied für eine kleine Änderung.

Cache-Server verwenden

Nun, da Sie Cache-Header nach ausgefeilten Regeln senden können, können Sie jetzt einen anderen Server benutzen, um Anfragen an Plone zu cachen. So schnell Zope auch ist, es kann nie schneller als Apache, Squid oder IIS sein, wenn es um die Ausgabe von Inhalten geht. Diese Server können statischen und gecachten Inhalt einfach und schnell ausgeben. Zum Teil liegt das daran, dass diese Server in C geschrieben sind, aber auch daran, dass sie bei jeder Anfrage weniger Arbeit haben. So gibt es keine Sicherheitsüberprüfungen, Datenbankabfragen oder Verhandlungen über die zu verwendende Sprache. Und als Sie Kapitel 10 gelesen haben, haben Sie außerdem schon einen Proxy-Server installiert.

Apache verwenden

Apache ist der Open-Source-Standard-Webserver. Die folgenden Abschnitte beschreiben Techniken für Apache 2.0 Server unter Linux. Mit nur geringen Änderungen an der Syntax funktionieren die meisten dieser Tipps auch unter Apache 1.3. Weitere Informationen zu verschiedenen Apache-Servern und -Plattformen finden Sie in der exzellenten Apache-Dokumentation unter http://www.apache.org.

Inhalte komprimieren

Die Möglichkeit, Ihre Seiten zu komprimieren, spart Bandbreite. Bevor eine Seite vom Server gesendet wird, wird sie schnell noch komprimiert, um vom Client wieder dekomprimiert zu werden. Damit lassen sich Seiten schneller herunterladen, und es fallen beim Besitzer der Site weniger Kosten wegen der verwendeten Bandbreite an, da die Dateien kleiner sind. Dazu aktivieren Sie zuerst das Modul mod_deflate. Das hängt von Ihren genauen Einstellungen ab. Unter Linux machen Sie z.B. Folgendes:

LoadModule cache_module modules/mod_deflate

Als Zweites fügen Sie Folgendes zu Ihrer Server-Konfiguration hinzu, um Texte in Hypertext Markup Language (HTML), Extensible Markup Language (XML) und einfache Texte zu dekomprimieren:

AddOutputFilterByType DEFLATE text/html text/xml text/plain

Manche Clients behandeln die Dekomprimierung etwas anders, d.h., es lohnt sich, die Dokumentation zu mod_deflate zu lesen, um detailliertere Beispiele zu sehen (http://httpd.apache.org/docs-2.0/mod/mod_deflate.html).

Ablauf-Header setzen

In den vorangegangenen Abschnitten haben Sie gesehen, wie Sie Ablauf-Header senden können, indem Sie Plone-Werkzeuge manipulieren. Mit Apache kann man diese Header ebenfalls leicht mit der Direktive ExpiresActive senden. Das ist eine Alternative zur Verwendung der verschiedenen Plone-Werkzeuge. Um z.B. für alle Bilder die Ablauf-Header auf 24 Stunden ab jetzt zu setzen, können Sie Folgendes zu Ihrer Apache-Site-Konfiguration hinzufügen:

ExpiresActive On
ExpiresByType image/gif "access plus 1 day"
ExpiresByType image/png "access plus 1 day"
ExpiresByType image/jpeg "access plus 1 day"

Weitere Informationen zu mod_expires finden Sie unter http://httpd.apache.org/docs-2.1/mod/mod_expires.html.

Caching in Apache

Apache enthält mehrere Systeme, die Caching-Aufgaben für Sie erledigen können. Das Apache-Standardmodul mod_cache hat zwei Caching-Modi: Memory und Disk. Dabei werden alle Seitenanfragen gemäß eines Satzes von Parametern für eine bestimmte Zeit gecacht. Um einen Cache auf der Platte im Ordner /tmp/apache_cache einzurichten, fügen Sie Folgendes zur Site-Konfiguration hinzu:

CacheRoot /tmp/apache_cache
CacheEnable disk /
CacheSize 256
CacheDirLevels 5
CacheDirLength 3

Leider kann es etwas schwierig sein, den Beweis zu erbringen, dass Apache den Inhalt wirklich im Cache speichert. Der einfachste Ansatz ist vielleicht der, es so zu testen, indem z2.log in Plone überwacht wird, um zu sehen, ob es getroffen wird. Weitere Informationen zu mod_cache finden Sie unter http://httpd.apache.org/docs-2.0/mod/mod_cache.html.

Squid verwenden

Squid ist ein Open-Source-Proxy-Server, der sehr oft zusammen mit Zope benutzt wird. Damit können Sie Zope beschleunigen, indem Sie Inhalte cachen, die in Squid erstellt werden, damit mehrere Anfragen von Squid und nicht von Zope bearbeitet werden. Auch hier gilt, dass Squid keine dynamischen Inhalte darstellt und in C geschrieben ist, d.h., es antwortet wesentlich schneller. In Kapitel 10 habe ich die Installation von Squid und dessen Einsatz als Proxy beschrieben. Wenn Sie Squid zur Beschleunigung von Plone benutzen möchten, lesen Sie bitte in diesem Kapitel die Angaben zur Einrichtung von Squid als Proxy-Server nach.

Wie Sie weiter oben in diesem Kapitel gesehen haben, können Sie mit dem Caching Policy Manager und dem Accelerated HTTP Cache Manager fast beliebige Informationen in HTTP-Headern unterbringen. Squid fungiert nun in ähnlicher Weise als Browser-Cache. Wenn eine Anfrage nach einer Seite kommt und diese Cache-Header vorhanden sind, wird Squid die Seite cachen. Wiederholte Treffer führen dazu, dass Squid und nicht Plone die Seite zurückgibt.

Ob eine Seite gecacht wurde, kann man relativ einfach sagen, da Squid den Header X-Cache zur Antwort hinzufügt. Mit dem Skript header.py können Sie sehen, ob die Seite erfolgreich gecacht wurde. Ein HIT bedeutet, dass Squid eine Kopie im Cache gefunden und zurückgegeben hat. Wenn keine Kopie gefunden und Plone gefragt wurde, wird ein MISS zurückgegeben. Beispiel:

X-Cache: HIT from http://www.agmweb.ca

Beim Testen in der Entwicklungsumgebung zeigt Squid beeindruckende Zahlen und beschleunigt die Anzeige einer Plone-Seite im Cache von etwa zwei Anfragen pro Sekunde auf mehr als 25 pro Sekunde. Benutzer haben berichtet, dass auf schnellen Servern relativ leicht Werte von 200 Anfragen pro Sekunde erreicht werden.

Squid-Caches säubern

Wenn ein Benutzer ein Objekt bearbeitet, ändert es sich in Plone. Da dieses Objekt aber in einem früheren Zustand gecacht ist, enthält der Cache eine alte Version. Benutzer, die auf die Site zugreifen, erhalten dann eine alte Version und nicht die neue. Wenn Sie die Caches beeinflussen können (wie bei Squid), können Sie PURGE-Befehle an den Caching-Server schicken, damit er Objekte aus dem Cache entfernt.

Beim Accelerated HTTP Cache Manager fügen Sie die URLs der Caches zu Notify URLs (via PURGE) hinzu. Hier ein Beispiel dafür:

http://192.168.1.1:80/example.org

In diesem Beispiel ist die IP-Adresse die Adresse des Caches, und die Domain ist die zu löschende Site. Damit Squid die PURGE-Direktive ausführt, müssen Sie sicherstellen, dass Squid konfiguriert ist. Falls Squid auf localhost läuft, sähe das wie folgt aus:

acl PURGE method purge
http_access allow localhost
http_access allow purge localhost
http_access deny purge
http_access deny all

Der Caching Policy Manager verfügt im Moment über keinen PURGE-Mechanismus, obwohl Sie ein Script (Python)-Objekt zum Workflow hinzufügen könnten, um das zu erreichen. Sie könnten den Python-Code in Listing 14.2 als externe Methode speichern und sie bei Bedarf im Workflow ausführen.

Listing 14.2. Ein Skript zum Löschen des Squid-Caches

import urllib
import urlparse
import httplib
 
URLs = [
    # enter the URLs you would like
    # to purge here
    'http://localhost:8080',
]
 
def purge(objectURL):
    for url in URLs:
        if not url:
            continue
        assert url[:4] == 'http', "No protocol specified"
 
        url = urlparse.urljoin(url, objectURL)
        parsed = urlparse.urlparse(url)
        host = parsed[1]
        path = parsed[2]
 
        h = httplib.HTTP(host)
        h.putrequest('PURGE', path)
        h.endheaders()
        errcode, errmsg, headers = h.getreply()
        h.getfile.read()
 
if __name__ == '__main__':
    print purge('/')

Das Collective-Projekt enthält ein neues Werkzeug namens CMFSquidTool, das Ihnen diese Arbeit abnimmt. Es beobachtet Änderungen am Inhalt, und wenn es eine entdeckt, sendet es für Sie ein Purge an den Squid-Cache. Ich habe es noch nicht ausprobiert, aber Sie sollten sich dieses Werkzeug definitiv anschauen, wenn Sie mit Squid arbeiten.

Säuberungen in Squid-Caches vermeiden

Säuberungen in Caches vermeidet man am besten durch selektiveres Caching. Sowohl der Caching Policy Manager als auch der RAM Cache Manager bieten Möglichkeiten zur selektiven Angabe dessen, was vom Cache zurückgegeben werden soll.

Vary

Der Caching Policy Manager und Squid unterstützen beide den Vary-Tag. Falls ein Vary-Tag angegeben wird, extrahiert Squid aus der Anfrage die im Vary-Tag angegebenen Header. Diese werden dann mit dem Cache verglichen. Wenn sie übereinstimmen, wird die Seite aus dem Cache zurückgegeben. Ansonsten wird die Anfrage an Plone weitergegeben.

Wenn der Vary-Tag im Caching Policy Manager z.B. den Wert Accept-Language hat und eine Anfrage an Squid kommt, wird die Seite gemäß der Einstellung Accept-Language in diesem Anfrage-Header gecacht. Wenn ein Benutzer eine Seite mit einer anderen Einstellung verlangt, wird eine neue Seite zurückgegeben. Das heißt, Sie können die Seiten nach Sprachen cachen.

Der am wenigsten aggressive Wert von Vary ist *, bei dem alle Anfragen gecacht werden, die mit anderen Anfragen identisch sind. Unterschiedliche Anfragen werden direkt an Plone weitergegeben. Auch wenn dies das am wenigsten aggressive Caching-System ist, garantiert es doch, dass der Benutzer nur aktuelle Inhalte sieht.

REQUEST-Methoden

Die REQUEST-Methoden des RAM Cache Managers verfolgen das gleiche Konzept wie Vary, außer dass das Werkzeug eine Liste von Zope-Anfragevariablen akzeptiert. Das Ergebnis einer Suche im Cache basiert dann auf diesen Variablen. Der voreingestellte Wert lautet AUTHENTICATED_USER, d.h., dass alle authentifizierten Benutzer ihre eigene Version des Caches sehen. Nicht registrierte (anonyme) Benutzer sehen alle den gleichen Inhalt.

Zope Enterprise Objects verwenden

Das letzte Wort bei der Skalierung und Administration von Plone ist es, ZEO (Zope Enterprise Objects) zu benutzen. Das ist ein wesentliches Werkzeug in sehr vielen Bereichen von Plone, sowohl für die Entwicklung als auch für die Produktion. Viele Leute denken, es sollte zu den Standardeinrichtungen von Plone gehören, und vielleicht wird es das bald. Im Moment wird unter Linux ZEO mit Plone ausgeliefert, aber nicht installiert. Es funktioniert auch unter Windows, wird dort aber nicht vollständig mit Diensten oder einer einfachen Installation unterstützt.

In einer normalen Plone-Installation gibt es eine Instanz von Plone, die mit einer Instanz der ZODB kommuniziert. Während diese eine Plone-Instanz auf die ZODB zugreift, wird diese gesperrt und kein anderer Prozess kann darauf zugreifen. Das beschränkt die Skalierbarkeit der Site und führt eine isolierte Schwachstelle ein. In der Welt relationaler Datenbanken wäre das gleichbedeutend damit, dass nur ein Prozess auf Ihre Datenbank zugreifen könnte.

ZEO bricht die Abhängigkeit auf und isoliert den Zugriff auf die ZODB (auch ZEO-Server genannt), damit mehrere Prozesse (auch ZEO-Clients genannt) sich mit der ZODB verbinden können, wie in Abbildung 14.9 zu sehen ist. In der Terminologie relationaler Datenbanken ist das äquivalent mit einem Prozess, der die Verbindung zur Datenbank herstellt.

img/14-09.png

Abbildung 14.9. Eine Standardkonfiguration von ZEO

Da sich mehrere Prozesse mit einer ZODB verbinden können, haben Sie nun die Möglichkeit, mit mehreren Kopien von Plone zu arbeiten. Im Wesentlichen könnten Sie nun zwei oder drei Plone-Instanzen mit dem gleichen Inhalt haben. Das heißt, Sie können nicht nur die Last Ihrer Site auf viele Computer verteilen, sondern können nun mit einem Programm eine Verbindung zu Ihrer Site herstellen und aufwendige Aufgaben auf anderen Computern ausführen oder Ihre Site zur Laufzeit auf Python-Ebene untersuchen.

Und schließlich ist ein auch nicht ganz unwesentlicher Punkt der, dass die Zeiten für einen Neustart eines ZEO-Clients sehr kurz sind. Der Aufwand beim Laden der Datenbanken entfällt, d.h., Sie können Plone-Sites schnell neu starten.

Installation von ZEO

ZEO ist in Zope 2.7 enthalten, der Zope-Version, die von diesem Buch unterstützt wird. In früheren Zope-Versionen war es separat verfügbar. Im Moment gibt es keine einfache Möglichkeit, ZEO unter Windows zu installieren. Das Skript mkzeoinstance funktioniert nicht. ZEO selbst funktioniert, wie es soll, aber Sie müssen die ZEO-Quellen lesen, um zu sehen, wie man das anstellt. Außerdem funktioniert zopectl nicht unter Windows, d.h., die folgenden Beispiele funktionieren dort ebenso wenig.

Linux

Um einen ZEO-Server zu erstellen, benutzen Sie das Skript mkzeoinstance im Verzeichnis /opt/Zope-2.7/bin. Das setzt voraus, dass Zope bereits wie in Kapitel 2 beschrieben installiert ist. Das Skript erwartet folgende Parameter:

  • Directory: Das Verzeichnis, in dem die ZEO-Server-Instanz erzeugt werden soll.
  • Host: Der Host und Port, an dem der Server reagieren sollte, im Format host:port. Der Port ist jener Port, mit dem sich ZEO-Clients verbinden, und sollte durch eine Firewall geschützt sein, da ZEO keine Sicherheit gegen unautorisierten Zugriff bietet. Parameter sind optional. Der voreingestellte Port ist 9999.
  • User und Password: Der vorgegebene Standardbenutzer und sein Passwort für den Server im Format benutzer:passwort. Ist optional.

Folgendes z.B. installiert ZEO unter /var/zeo auf dem Standard-Port:

cd /opt/Zope-2.7/bin
./mkzeoinstance /var/zeo

Hierdurch wird eine neue Datenbank mit der entsprechenden Konfiguration erstellt. Diese Datenbank ist an einem neuen Ort, aber das ist in Ordnung. Wenn Sie eine existierende Zope-Installation mit ZEO aufrüsten wollen, dann müssen Sie das laufende Zope anhalten und dann die Datenbank von Ihrer alten Installation in das neue ZEO-Verzeichnis verschieben. In meinem Fall heißt das, die Datei Data.fs von /var/zope/var nach /var/zeo/var zu verschieben.

Als Nächstes müssen Sie die Konfiguration Ihrer Zope-Instanz ändern. Öffnen Sie dazu zope.conf in etc, und geben Sie folgende Information ein:

# ZEO client storage:
#
<zodb_db main>
   mount-point /
   <zeoclient>
     server localhost:9999
     storage 1
     name zeostorage
     var $INSTANCE/var
   </zeoclient>
</zodb_db>

Im obigen Code geben Sie den Port und den Server an, auf dem sich der ZEO-Server befindet. Außerdem müssen Sie die vorhandene Abbildung auf die lokale Datenbank auskommentieren. Das sollte etwa wie folgt aussehen:

#<zodb_db main>
#    # Main FileStorage database
#    <filestorage>
#      path $INSTANCE/var/Data.fs
#    </filestorage>
#    mount-point /
#</zodb_db>

Um zu testen, ob das funktioniert, starten Sie zuerst den ZEO-Server. Dazu sind eventuell mehr Rechte notwendig, als der Benutzer hat, unter dem Sie ihn installiert haben:

$ cd /var/zeo/bin
$ ./zeoctl start
daemon process started, pid=29316

Der ZEO-Daemon wurde erfolgreich gestartet. Starten Sie nun einen Zope-Client, und versuchen Sie, sich z.B. wie folgt damit zu verbinden:

$ cd /var/zope/bin
$ ./zopectl start
daemon process started, pid=29338

Das macht alles einen guten Eindruck, und Sie können nun wie gewohnt auf Ihr Plone zugreifen.

ZEO-Clients benutzen

In dieser Konfiguration wird über den ZEO-Server auf die ZODB zugegriffen, und jede Zope-Instanz ist ein ZEO-Client. Mehrere ZEO-Clients können mit dem Server eine Verbindung aufbauen. Client und Server müssen keineswegs auf dem gleichen Rechner laufen, solange der Client eine Verbindung zum Server herstellen kann. Falls die Clients auf dem gleichen Computer sind, muss sich jeder Client an einen anderen HTTP- und FTP-Port binden, um Konflikte untereinander zu vermeiden.

Wenn Ihr Client startet, verbindet er sich mit dem Speicher, der in Ihrer Konfiguration angegeben ist, statt mit dem lokalen Standardspeicher. Eine häufige Anforderung ist die, einen zusätzlichen Rechner zu erlauben, auf dem rechenintensive Aufgaben laufen, z.B. eine Aktualisierung des Katalogs, eine Komprimierung der Datenbank oder eine Durchführung komplexer Abfragen, ohne dass die Performance der anderen Clients sinkt. Mit der Funktion zopectl lässt sich das recht einfach machen:

$ cd /var/zope/bin
$ ./zopectl debug
Starting debugger (the name "app" is bound to the top-level Zope object)

Um die Datenbank zu komprimieren, würden Sie dann Folgendes machen:

>>> app.Control_Panel.Database.manage_pack(days=0)

Weil Sie einen ZEO-Client ausführen, müssen Sie dem Server sagen, dass eine Änderung vorgenommen wurde und die Caches aktualisiert wurden. Schließen Sie die Transaktion wie folgt ab:

>>> get_transaction().commit()
>>> app._p_jar.close()

Das empfiehlt sich besonders dann, wenn Sie eine hochperformante Site betreiben und die Datenbank komprimieren müssen. Die Site wird ein wenig langsamer laufen, wenn die Transaktion beendet wird, aber der größte Teil der schweren Arbeit erfolgt auf dem Client, der die Komprimierung durchführt. Das könnte ein von Ihrer Site völlig verschiedener Rechner sein. Daher ist das eine hervorragende Methode, die Last zu verteilen.

Bei der Fehlersuche ist es extrem hilfreich, zu diesem Prompt zu gelangen, da Sie dort die Objekte in diesem app-Objekt untersuchen können. Sie werden feststellen, dass sie mit den Objekten übereinstimmen, die Sie im ZMI sehen. Beispiel:

>>> app.objectIds()
['acl_users', 'Control_Panel', 'temp_folder',...

Wie lautet die API für dieses app-Objekt? Sie können die eingebaute Python-Funktion dir benutzen, um das Objekt zu untersuchen und sogar die Methode __doc__, um die darin enthaltenen Kommentar-Strings wie folgt zu sehen:

$dir(app)
>>> dir(app)
['COPY', 'COPY__roles__', 'Control_Panel', 'DELETE',...
>>> app.valid_roles.__doc__
'Return list of valid roles'

Ein gutes Beispiel einer ZEO-basierten Anwendung ist CMFNewsFeed (http://sf.net/projects/collective). Sie stellt eine Verbindung zu Plone mit einem ZEO-Client her. Dieser separate Client legt dann los und sammelt alle Nachrichten, die er finden kann, und fügt die Daten in die Site ein. Dadurch, dass alles Sammeln und Katalogisieren in einem separaten Prozess läuft, wird garantiert, dass die Performance der Haupt-Site hoch bleibt.

Für Entwickler ist ZEO ein unverzichtbares Werkzeug. Damit können Sie durch ein Programm mit Ihrem Server interagieren, während er läuft. Wenn Sie als erfahrener Programmierer an dieser Stelle immer noch verwirrt sein sollten, was Plone und die Objektdatenbank angeht, dann öffnet Ihnen ZEO normalerweise die Augen.

Lastverteilung und Ausfallsicherung

Obwohl ZEO die Möglichkeit bietet, Plone auf vielen Servern zu betreiben, hat es für den Benutzer nichts zu bieten, womit er eine Lastverteilung vornehmen könnte. Unter Lastverteilung (engl. load balancing) versteht man, dass hereinkommende Anfragen auf verschiedene Server gesendet werden, um die Last der Seitengenerierung zu verteilen. Ausgefeilte Werkzeuge testen, ob der Server überhaupt läuft, bevor sie ihm eine Anfrage schicken.

Bei der Verteilung der Last haben Sie Hardware- und Software-Möglichkeiten. Squid z.B. beherrscht die dynamische Ausfallsicherung (engl. failover). Pound ist ein Beispiel für ein Lastverteilungssystem, das Sie unter http://www.apsis.ch/pound/index.html finden.

Squid kennt das Internet Cache Protocol (ICP), ein Protokoll, mit dem es prüfen kann, ob eine Plone-Site läuft, bevor Anfragen an sie weitergereicht werden. Auf hochgradig dynamischen Sites ist das eventuell ein Muss. Weitere Informationen zu ICP und Zope finden Sie unter http://www.zope.org/Members/htrd/icp/intro.


Andy McKay: Plone. Addison-Wesley 2005
Diese online Version wurde mit Hilfe des 'PloneBookDE' Produkts von docs.neuroinf.de/products erstellt.
Es wurde zuletzt von
loesch am 2006-01-11 13:38 aus der fallback Quelle aktualisiert.

Powered by Plone CMS, the Open Source Content Management System

This site conforms to the following standards: