toscho.design

WordPress: WP-Cron begrenzen

So sehr ich WordPress auch schätze – einige Macken gehen mir tüchtig auf die Nerven. Dazu gehören auch die vielen Requests auf wp-cron.php?doing_wp_cron.
Solch ein Request wird bei (fast?) jedem Aufruf einer Seite oder eines Artikels angestoßen. Zwar werden dabei kaum Daten übertragen, aber ein bißchen Zeit kostet es eben doch, und das Logfile wächst ohne Not.

Ich habe mir deshalb in die Konfigurationsdatei wp-config.php diese kleine Einschränkung eingetragen:

if ( 0 < (time() % 10) )
{
    define('DISABLE_WP_CRON', TRUE);
}

Zu Deutsch: Wenn sich der aktuelle, in Sekunden gemessene UNIX-Timestamp nicht genau durch 10 teilen läßt, verzichte ich auf WP-Cron.

Damit funktionieren noch die Kontrollen auf neue Plugin- oder WordPress-Versionen, doch die Menge der Requests schrumpft dramatisch. Wer noch weniger Aufrufe haben möchte, der erhöhe einfach den Teiler.

Natürlich könnte man die Pseudo-Cronjobs auch einfach komplett abschalten und einen richtigen Cron benutzen. WordPress sendet aber einen POST-Request, dessen Zusammensetzung ich nach jedem Update neu überprüfen müßte, um den echten Cron entsprechend anzupassen. Das ist mir zu umständlich.

Einen guten Überblick über die anstehenden Cronjobs bekommt man mit dem Plugin Cron View. Das sieht dann ungefähr so aus:

Cron View

Wer gerne Plugins ausprobiert, sollte sich das unbedingt mal ansehen, denn nicht jeder Autor schreibt eine saubere Deinstallation.

10 Kommentare

  1. David am 30.01.2010 · 23:10

    Prüft wp-cron lediglich auf evtl. vorhandene Updates der Plugins und des Kernprogramms? Dann kann man das doch gleich abschalten.

  2. Thomas Scholz am 30.01.2010 · 23:16

    @David: Auch Plugins können diese API benutzen, etwa zum regelmäßigen Backup oder für Terminkalender. Und wenn du einen Beitrag erst in der Zukunft veröffentlichen möchtest, wird ebenfalls WP-Cron benutzt.
    Wenn wirklich nur Plugins und Core geprüft werden, dann kannst du es abschalten, wenn es in deiner lokalen Kontrollinstallation noch angeschaltet ist.

  3. daniel am 20.02.2010 · 16:48

    Ich werde deinen Vorschlag gleich mal umsetzen! Hört sich jedenfalls sehr sinnvoll an!

  4. Patrick am 14.03.2010 · 14:11

    Hmm wie wäre es, wenn du die cronjobs nur zu bestimmten Zeiten ausführen lässt, anstatt Sekunden mod 10 = 0 zu nutzen? Dazu müsstest du lediglich irgendwo abspeichern, wann das letzte mal der "cronjob" ausgeführt wurde.

  5. Thomas Scholz am 14.03.2010 · 17:12

    @Patrick: Das kann man auch machen, beispielsweise so:

    // Cron nur in der vorletzten Stunde des Tages
    if ( 22 != (int) date('H') )
    {
        define('DISABLE_WP_CRON', TRUE);
    }

    Zu eng darf man den Zeitraum bei schwach besuchten Seiten nicht fassen, denn der WP-Cron startet nur bei einem externen Request. Und ich würde ihn lieber nicht auf eine Zeit legen, die von der Zeitumstellung berührt wird.

  6. Jürgen am 06.06.2010 · 09:08

    Hallo, erstmal,
    ich halte deine Idee nur für auf den ersten Blick interessant.
    Denn wenn deine Seite wenig Besucher hat, dann bringt es auch keine nennenswerte Entlastung, wenn der WP-Cronjob nur alle volle 10 Sekunden läuft. Wenn Du Pech hast, dann läuft der Cronjob sehr lange Zeit gar nicht. Die Wahrscheinlichkeit ist 1:10.
    Und wenn Deine Seite häufig aufgerufen wird (egal ob durch Menschen oder Maschinen), musst Du dich auf andere Art und Weise vor Überlastung schützen. Ich denke nicht, dass dein Hack dann viel Entlastung bringt. Apache juckt sich nicht viel um einen weiteren Zugriff, das muss er auch so verpacken. Allenfalls könnte MySQL ins Schwitzen kommen. Hast Du schonmal versucht, die Anzahl der Request mit und ohne deinen Hack zu vergleichen? Das kann man z.B. im Footer jeder Seite ausgeben.
    Wirklich etwas würde es meiner Meinung nach bringen, wenn Du den internen Cronjob komplett deaktivieren würdest und stattdessen "wp-cron.php?doing_wp_cron" durch einen richtigen Cronjob aufrufen würdest.

  7. Thomas Scholz am 06.06.2010 · 13:02

    @Jürgen: Der Performancegewinn liegt im Vergleich zu anderen Faktoren sicher nicht sehr hoch. Ich reduziere den WP-Cron vorrangig deshalb, weil ich das Logfile übersichtlich halten möchte. Das gelingt einigermaßen.

    Allenfalls könnte MySQL ins Schwitzen kommen. Hast Du schonmal versucht, die Anzahl der Request mit und ohne deinen Hack zu vergleichen? Das kann man z.B. im Footer jeder Seite ausgeben.

    Die MySQL-Requests der wp-cron.php sind von der HTML-Ausgabe aus nicht so einfach einsehbar, dazu müßte ich sie alle mitloggen (langsam). Obendrein benutze ich hier einen Query-Cache, was das Ergebnis weiter verzerrt.

    Wirklich etwas würde es meiner Meinung nach bringen, wenn Du den internen Cronjob komplett deaktivieren würdest und stattdessen "wp-cron.php?doing_wp_cron" durch einen richtigen Cronjob aufrufen würdest.

    Ich benutze den internen Cron hauptsächlich für »Zukunftsbeiträge«, die erst ab einer bestimmten Zeit publiziert werden. Die Synchronisation mit dem echten Cron ist zwar möglich, aber ein bißchen zu aufwendig, finde ich. Plugins und den Core aktualisiere ich immer von der lokalen Installation aus, nachdem ich sie gründlich getestet habe.

    Eine Alternative zu meinem oben skizzierten Code bietet das Plugin Core Control. Damit kann man genau festlegen, was geprüft wird (Themes, Core, Plugins).

  8. Martin am 30.06.2010 · 18:32

    Hi Thomas,

    ich habe dich gerade (virtuell) im Support Forum des WordPress Database Backup Plugins "getroffen" und festgestellt, dass du das gleiche Problem mit wiederholten Backups hattest wie ich. Ich habe den Plan zwar nur eingestellt auf ein wöchentliches Backup, aber trotzdem habe ich heute (nicht zum ersten Mal) im Minutentakt per E-Mail neue Backups bekommen. 84 Stück an der Zahl, zum Glück ist meine Datenbank ist sicher um einiges kleiner als deine. Aber wenn ich mal im Urlaub oder gerade nicht am Rechner bin, möchte ich ungern Zillionen Backup-E-Mails empfangen...

    Im Forum gab es ja leider keine Lösung - was wahrscheinlich auch schwierig ist, da es an vielen Faktoren hängen kann, die nicht mit dem Plugin zusammenhängen. Du schriebst ja selbst, dass es bei dir in einigen Blogs ohne Probleme funktioniert, hast du denn da Unterschiede bei anderen Plugins oder deinen Änderungen im Core?
    Ich habe auch zwei Kunden-Blogs, in denen es keine Probleme gibt. Aber in meinem eigenen habe ich einige kleinere Core-Änderungen (nach deiner Anleitung ☺) gemacht und auch andere Plugins als bei den Kunden-Blogs.
    Aber im Support-Forum gibt's ja auch einen dritten Kommentator mit dem gleichen Problem.

    Ich nehme an, dass du das Problem entweder bereits selbst gelöst hast oder auf ein anderes Plugin umgestiegen bist. Hast du zum Beispiel Erfahrungen mit dem WP-DBManager von Lester 'GaMerZ' Chan?

    Leider habe ich keinen besseren Artikel (zum Thema Backups) bei dir gefunden, in dem ich meine Frage stellen konnte, dieser kommt meiner Frage am nächsten, denke ich, da das Backup ja auch mit cron-Jobs zusammenhängt.

  9. Thomas Scholz am 05.07.2010 · 16:53

    @Martin: Hast du das Problem bei All-Inkl.com? Hier trat das bei mir nur an der ersten angelegten Mail-Adresse auf (info@). Inzwischen habe ich eine separate Adresse für Systemmeldungen angelegt, und dort bekomme ich nur eine Mail pro Backup.
    Damit ist natürlich die Ursache noch nicht geklärt. Leider.

    Vielleicht bittest du deinen Hoster mal um ein erweitertes Mailprotokoll. Wenn du dahintersteigst, dann schick die Lösung doch bitte dem Pluginautor; der möchte das sicher auch lösen.

  10. Andreas am 09.08.2011 · 10:42

    Hallo,
    ich glaube auch, man muss hier zwischen gut und schlecht besuchten Sites unterscheiden. Bei gut besuchten ist das oben sicher eine gute Lösung. bei schlecht besuchten wäre z.B. eine andere Lösung besser, die bewirkt, dass nach einem Aufruf von WP_Cron die WP_Cron zunächst für z.B. mindestens 1min, 15min, 30min, 1h oder wie lang auch immer schläft. Wahrscheinlich krigt man das auch einfach hin, indem man einfach einen Zeitstempel beim Laufen des WP_CRON setzt und dann ähnlich wie oben beim nächsten Aufruf schaut, ob schon genügend Zeit vergangen ist ...