Drupal ist extrem flexibel, vielseitig und kann für unterschiedlichste Projekte und Projektgrößen eingesetzt werden. In diesem Blogeintrag möchte ich einige Hinweise für High-Traffic Websites mit Drupal niederschreiben. Ich beziehe mich dabei NICHT mehr auf bekannte Optimierungstipps, sondern eher auf Besonderheiten, die Euch und mir in Zukunft helfen, Besonderheiten in solchen Fällen zu begegnen. Los gehts!
Wichtig!! Diese Hinweise bringen Eure Drupal Website nicht unbedingt auf Geschwindigkeit, wenn die zugrundeliegenden Probleme nicht auf Euch zutreffen. Ihr solltet also nicht blind all diese Tricks anwenden, sondern die Performancebremsen in Eurem Problem identifizieren und mit diesen Tipps prüfen, ob Abhilfe geschafft werden kann.
Caching in der Datenbank (cache_*)
Drupal liefert ein umfassendes Caching built-in mit. Selbst wenn man dieses deaktiviert, werden bestimmte Konfigurationen stets gecached, um Performance sicherzustellen und einmalige Berechnungen nicht mehrfach durchzuführen.
In einem Projekt gab es dadurch allerdings das Problem, dass beim Einsatz zahlreicher benötigter contrib-Module die Caches in Massen in die Datenbank geschrieben wurden. Das eigentliche Datenbank-Caching wurde dadurch ineffizient.
Ein guter Trick ist daher, alle "cache_*" Tabellen via filecache.module (als einfache Ablage in der Festplatte - tendenziell eher "langsamer") oder In Memory Techniken (memcache.module / memcache_storage.module / apc.module) aus der Datenbank heraus zu nehmen. In unserem Fall war dies sehr sehr hilfreich und die Datenbank konnte "aufatmen".
Die "semaphore"-Tabelle & InnoDB
Details zur Locking-Technik in Drupal findet ihr hier: https://api.drupal.org/api/drupal/includes!lock.inc/group/lock/7
Wir setzen als Standard Datenbank-Engine InnoDB ein. Das ist soweit gut. Mithilfe des folgenden MySQL Snippets konnte ich allerdings herausfinden, dass es in der "semaphore" Tabelle immer wieder zu Deadlocks kommt:
Die tatsächliche Ursache liegt vermutlich in contrib-Modulen kombiniert mit einer hohen Concurrency und muss noch weiter analysiert werden.
Ein guter Trick, um diesem Problem effizienter aus dem Weg zu gehen (und häufig diskutiert, z.B. hier: http://www.workhabit.com/blog/drupal-innodb-and-myisam-engine-issues-ca… ist es, diese EINZELNE TABELLE auf MyISAM umzustellen, um nicht in Probleme mit dem InnoDB Locking zu laufen. Die Umschaltung könnt ihr z.B. via PhpMyAdmin oder SQL-Befehl durchführen, aber Achtung, denkt an Sicherungen vorab!
Ihr findet hier weitere Hinweise, wie ihr Problemen mit Locks auf die Spur kommt: http://www.xaprb.com/blog/2006/07/31/how-to-analyze-innodb-mysql-locks/
Auch auf Drupal.org gibt es einen Beitrag mit wichtigen Tipps:
https://groups.drupal.org/node/415883
Zudem solltet ihr einen Blick auf wichtige generelle Hinweise zur Optimierung der InnoDB werfen. Es gilt zu prüfen, welche davon im konkreten Fall hilfreich sind.
INNODB: tx isolation auf READ-COMMITTED setzen
Wie schon im vorhergehenden Punkt beschrieben, gibt es einige Probleme mit LOCKs in den Drupal Tabellen. Insbesondere die Variablen-Tabelle ist ein Nadelöhr bei High-Traffic Websites.
Die Änderung des tx isolation level auf READ-COMMITTED ist damit für INNODB-Engines ein riesiges Thema.
transaction-isolation = READ-COMMITTED
INNODB: innodb_flush_log_at_trx_commit auf "2" setzen
https://drupal.org/node/817398
Dieser Beitrag erklärt die Vorteile und Nachteile. Eine gute Dokumentationsseite zum Thema findet sich leider trotzdem nicht.
innodb_flush_log_at_trx_commit = 2
Statisches Caching für anonyme Benutzer + AJAX
Ein selbstverständliches Thema für High-Traffic Seiten ist das statische Caching z.B. via boost.module. Dies entlastet die Seite für ausgeloggte Benutzer extrem.
Dynamische Teilinhalte lassen sich via AJAX einbinden. Gute Erfahrungen habe mit dem ajaxblocks.module.
Sofern das Drupal "Statistics" Core-Modul unumgänglich ist, sollte die AJAX-Option (seit 7.25) unbedingt verwendet werden.
Drupal Core Fast404 aktivieren
Insbesondere, wenn die Seite von einer alten URL migriert wurde, kann durch schnelle 404's einige Last vom Server genommen werden, indem man Pfade ausschließt, die nicht existieren können.
Dazu die entsprechenden Zeilen in der settings.php auskommentieren. Die Funktion ist Core, es wird kein Hilfsmodul wie fast404.module benötigt.
Siehe: https://drupal.org/node/1313592
/**
* Fast 404 pages:
*
* Drupal can generate fully themed 404 pages. However, some of these responses
* are for images or other resource files that are not displayed to the user.
* This can waste bandwidth, and also generate server load.
*
* The options below return a simple, fast 404 page for URLs matching a
* specific pattern:
* - 404_fast_paths_exclude: A regular expression to match paths to exclude,
* such as images generated by image styles, or dynamically-resized images.
* If you need to add more paths, you can add '|path' to the expression.
* - 404_fast_paths: A regular expression to match paths that should return a
* simple 404 page, rather than the fully themed 404 page. If you don't have
* any aliases ending in htm or html you can add '|s?html?' to the expression.
* - 404_fast_html: The html to return for simple 404 pages.
*
* Add leading hash signs if you would like to disable this functionality.
*/
$conf['404_fast_paths_exclude'] = '/\/(?:styles)\//';
$conf['404_fast_paths'] = '/\.(?:txt|png|gif|jpe?g|css|js|ico|swf|flv|cgi|bat|pl|dll|exe|asp|htm)$/i';
$conf['404_fast_html'] = '
Not Found
The requested URL "@path" was not found on this server.