Linuchs: Webserver-Überlastung?

Moin,

auf einem Webserver (eigene Hardware beim Provider) läuft eine öffentliche Domain, die z.Z. alle 3,3 s eine Webseite ausliefert, wohl zu 95% Bots. Ich lasse mir die Durchlaufzeit anzeigen, die varriiert extrem von 0,1 s bis 16 s auf derselben Seite. Was über 2 s läuft, meldet sich per Mail.

Der Server versorgt auch andere Domains. Was passiert genau, wenn eine Anfrage kommt und noch an einer anderen Seite "gearbeitet" wird?

Offenbar wird die Bearbeitung gestartet, denn die Zeit läuft. Und nach dem Start geht's in die Warteschlange und vorherige Aufgaben werden erst abgearbeitet?

Ist Apache multi-tasking-fähig?

Ich weiß nicht so recht, ob eine Adressliste mit 600 Zeilen wirklich "normal" 4,63 s braucht.

[SERVER_SOFTWARE|Apache/2.2.16 (Debian)]

Linuchs

  1. Hallo Linuchs,

    auf einem Webserver (eigene Hardware beim Provider) läuft eine öffentliche Domain, die z.Z. alle 3,3 s eine Webseite ausliefert, wohl zu 95% Bots. Ich lasse mir die Durchlaufzeit anzeigen, die varriiert extrem von 0,1 s bis 16 s auf derselben Seite. Was über 2 s läuft, meldet sich per Mail.

    16s ist aber extrem lang. Wie misst du das?

    Der Server versorgt auch andere Domains. Was passiert genau, wenn eine Anfrage kommt und noch an einer anderen Seite "gearbeitet" wird?

    Das hängt vom MPM-Modul des Apache ab. Wenn Prefork benutzt wird, dann kann es schon vorkommen, dass gewartet werden muss weil alle Worker gerade zu tun haben. Bei einem Hit alle 3,3s klingt das aber nicht unbedingt danach.

    Offenbar wird die Bearbeitung gestartet, denn die Zeit läuft. Und nach dem Start geht's in die Warteschlange und vorherige Aufgaben werden erst abgearbeitet?

    Nur, wenn die Worker alle gleichzeitig beschäftigt sind. Und auch dann wären 16s viel zu viel, um es nur auf eine volle Queue zu schieben.

    Ist Apache multi-tasking-fähig?

    Ja 😂

    Ich weiß nicht so recht, ob eine Adressliste mit 600 Zeilen wirklich "normal" 4,63 s braucht.

    Das hängt von vielen Faktoren ab. Was ist das für eine Hardware? Wie genau arbeitet dein Programm? Wieviel Speicher muss beim erstellen der Liste reserviert & kopiert werden? Etc, pp. Performance-Analysen sind nicht trivial.

    LG,
    CK

    1. Hallo Christian,

      16s ist aber extrem lang. Wie misst du das?

      list($usec, $sec) = explode(" ", microtime());
      $pr_start = (float)$usec + (float)$sec;
      ... 
      list($usec, $sec) = explode(" ", microtime());
      $pr_ende = (float)$usec + (float)$sec;
      $dauer   = sprintf( '%.3f', round(($pr_ende - $pr_start) *1000) /1000 );
      

      Linuchs

      1. Hallo Linuchs,

        16s ist aber extrem lang. Wie misst du das?

        list($usec, $sec) = explode(" ", microtime());
        $pr_start = (float)$usec + (float)$sec;
        ... 
        list($usec, $sec) = explode(" ", microtime());
        $pr_ende = (float)$usec + (float)$sec;
        $dauer   = sprintf( '%.3f', round(($pr_ende - $pr_start) *1000) /1000 );
        

        In dem Fall hat der Apache dein Script ja schon gestartet wenn die Messung beginnt. Es scheint also nicht der Apache der Flaschenhals zu sein. Für mehr muss man mehr analysieren. Typische Flaschenhälse sind zu wenig Speicher verfügbar, zu viel Speicher genutzt, konkurrierende exklusive Locks, I/O pressure und CPU pressure. Das würde ich zuerst überprüfen.

        Wenn es danach noch lahm ist, würde ich eine Sourcecode-Analyse machen.

        LG,
        CK

      2. Tach!

        list($usec, $sec) = explode(" ", microtime());
        $pr_start = (float)$usec + (float)$sec;
        

        Umständlich und nicht mehr nötig. Seit langem kann man microtime() mit true als Parameter aufrufen, um direkt den Float-Wert zu bekommen.

        dedlfix.

        1. Umständlich und nicht mehr nötig.

          Seit 2001 mache ich Webseiten mit PHP. Damals mit extrem vielen Tricks, besonders beim CSS. Oh, die gerundeten Ecken ... Wochen und Monate habe ich für den Gott Internet-Explorer geopfert, der damals den Anspruch erhob, Zeus (Ober-Gott) zu sein.

          In laufenden Programmen sind noch "alte" Formulierungen vorhanden, denn Programme werden mit include zusammengesetzt.

          Wenn ich die nach jedem Update von CSS, HTML, PHP, MySQL, Apache, ... "aktualisieren" wollte, käme ich nicht zur Weiter-Entwicklung.

          Ich stehe dazu, "Oldtimer" in der PC-Garage zu haben 😉

          Linuchs

  2. Hallo Linuchs,

    von Serverdingen habe nahezu keine Ahnung, aber Erfahrungswerte, die vielleicht helfen könnten. In einem ähnlichen Fall, vor Jahren, hatte ich dein/ähnliches Problem häufiger. Da mein Provider nicht helfen konnte, blieb mir nur try&error, letztendlich lag es bei mir an der Keep-Alive Einstellung, als ich die deaktiviert hatte, funktionierte alles blitzschnell, reproduzierbar. Was Keep-Alive nun wirklich macht(Theorie habe ich gelesen, pratisch verstanden eher nicht) konnte auch mein Provider nicht erklären. Vielleicht hilft dir der Hinweis.

    Gruss
    Henry

    1. Hallo Henry,

      Keepalive hält, nach Vereinbarung zwischen Browser und Server, die HTTP Verbindung offen und erlaubt das Anfordern weiterer Ressourcen über die existierende Verbindung.

      Vorteil: Es muss keine neue Verbindung von Grund auf hergestellt werden (bei Vorliegen von Authentication-Headern interesssant)

      Nachteil: Die Verbindung wird bis zum Ende des Keepalive-Timeout gehalten und Server-Ressourcen gebunden.

      Im Intranet meiner Firma ist Keepalive verboten. Grund: der Client bleibt während des Keepalive an einen Server gebunden und kann bei hoher Last nicht auf einen anderen Server im Cluster ausweichen.


      Hallo Linuchs,

      in einer Anwendung von mir habe ich SQL Messung eingebaut. D.h. vor Beginn jedes SQL Request hole ich mir microtime(true), nach Rückkehr nochmal, bilde die Differenz und summiere das auf. Dann weiß ich am Ende, wieviel Prozent meiner Laufzeit im SQL verbraten wurde.

      Wenn du andere Sache im Script hast, die auf externe Ressourcen zugreifen, kann es sich lohnen, auch da die Zeit zu messen.

      Rolf

      --
      sumpsi - posui - clusi
      1. in einer Anwendung von mir habe ich SQL Messung eingebaut. D.h. vor Beginn jedes SQL Request hole ich mir microtime(true), nach Rückkehr nochmal, bilde die Differenz und summiere das auf. Dann weiß ich am Ende, wieviel Prozent meiner Laufzeit im SQL verbraten wurde.

        Das finde ich einigermaßen umständlich und nur geringfügig aufschlussreich. Leichter hat man es mit einem Profiler. xdebug bringt einen solchen mit, das sollte sowieso auf jeder Entwicklungsumgebung laufen. Mit QCacheGrind bzw. KCacheGrind kann man dann diverse Diagrammarten erstellen und interaktiv durchforsten. So ist der Flaschenhals schnell ausgemacht.

        1. Hallo 1unitedpower,

          das hilft mir nicht auf dem Zielserver, wenn ich dort kein Admin bin und der Admin selbst relativ desinteressiert ist. Das ist keine kommerzielle Sache gewesen.

          Ein Profiler neigt vor allem dazu, ordentlich Ressourcen zu fressen, den kannst Du nicht ständig mitlaufen lassen.

          Rolf

          --
          sumpsi - posui - clusi
          1. das hilft mir nicht auf dem Zielserver, wenn ich dort kein Admin bin und der Admin selbst relativ desinteressiert ist. Das ist keine kommerzielle Sache gewesen.

            Das stimmt.

            Ein Profiler neigt vor allem dazu, ordentlich Ressourcen zu fressen, den kannst Du nicht ständig mitlaufen lassen.

            Für Produktivsysteme gibt es auch sogenannte passive Profiler, zum Beispiel von blackfire.io, die zeichnen sich durch kaum messbaren Performance-Overhead aus.

            (Edit by Rolf: Klartext gefixt - wer weiß welcher Typospammer sonst den Zuschlag bekommt)

            1. Hallo 1unitedpower,

              ok, für eine kommerzielle Seite mit viel Traffic sind 20€ im Monat sicherlich machbar. Ob es jemandem recht ist, Profiling-Daten an eine SaaS Plattform abzugeben, muss jeder für sich entscheiden. Da sie Geld für den Dienst nehmen, besteht die Chance dass das Geschäftsmodell nicht im Verkauf der gesammelten Daten besteht.

              Blackfire does nothing when you are not profiling a request (the overhead is then almost zero), so it is safe to deploy Blackfire on production servers, even for heavy-traffic projects.

              Das lese ich so, dass ich das Profiling jederzeit aktivieren kann. Ist es nicht aktiviert, kostet es nichts. Ist es aktiviert, kostet es aber.

              Wenn ich einen ständigen Watchdog will, der bei „zu lange“ laufenden SQL Requests loskläfft, hilft das nicht, glaube ich.

              Rolf

              --
              sumpsi - posui - clusi
              1. Wenn ich einen ständigen Watchdog will, der bei „zu lange“ laufenden SQL Requests loskläfft, hilft das nicht, glaube ich.

                Slow-Query-Log?

                EDIT: Ah, sorry. Du hast ja unkontrollierte Umgebungen angeführt, dann steht Dir die Option evtl. nicht zur Verfügung. Würde ich dann im Fall der Fälle aber auch in eine kontrollierte Umgebung (z.B. lokale Virtualisierung) überführen wollen und dort messen.

              2. ok, für eine kommerzielle Seite mit viel Traffic sind 20€ im Monat sicherlich machbar. Ob es jemandem recht ist, Profiling-Daten an eine SaaS Plattform abzugeben, muss jeder für sich entscheiden.

                Das war ja nur ein Beispiel, wenn man nach "passive php profiler" sucht, findet man auch kostenlose und quelloffene Lösungen. Da hat man eben keinen Support und mehr Aufwand bei der Inbetriebnahme.

                Blackfire does nothing when you are not profiling a request (the overhead is then almost zero), so it is safe to deploy Blackfire on production servers, even for heavy-traffic projects.

                Das lese ich so, dass ich das Profiling jederzeit aktivieren kann. Ist es nicht aktiviert, kostet es nichts. Ist es aktiviert, kostet es aber.

                Klar, ganz ohne Overhead gibt es kein Profiling, bei passiven Profilern liegt dieser aber im vernachlässigbaren Bereich.

                Wenn ich einen ständigen Watchdog will, der bei „zu lange“ laufenden SQL Requests loskläfft, hilft das nicht, glaube ich.

                Blackfire hat auch eine Alarmierungsfunktion, bei anderen Profilern bin ich mir jetzt nicht sicher. Aber die eigentliche Arbeit geht ja auch erst nach dem Alarm los, nämlich wenn der Bremsklotz gefunden werden muss, und ohne Profiler kämpft man da mit Schwertern gegen Windmühlen.

                Nur damit das nicht in den Hintergrund gerät: meine Empfehlung ist zuerst mit einem aktiven Profiler auf einer lokalen Entwicklugsumgebung nach Engpässen zu suchen. Der passive Profiler auf dem Zielsystem spielt eher die Rolle eines Langzeit-EKGs, womit man sporadisch auftretende Unregelmäßigkeiten analysieren kann, oder Szenarien, die man auf dem lokalen System nicht reproduzieren kann.

  3. Was passiert genau, wenn eine Anfrage kommt und noch an einer anderen Seite "gearbeitet" wird?

    Steht im Handbuch für prefork, welches Du vermutlich hast.

    Für den Laie: Der Apache (mit Root-Rechten, weil er an den Ports 80 und 443 lauschen will) setzt sich hin und Kinder(Subprozesse ohne Root-Rechte) in die Welt, die er für sich arbeiten lässt. Deren Anzahl reguliert er. Die Kinder nimmt er der Reihe nach an die Kandare und drückt denen die Anfrage zum Beantworten auf, lässt das jeweilige Kind dann machen. Ist das Kind fertig, dann stellt es sich brav wieder an.

    Es können also mehrere Anfragen parallel beantwortet werden.

    Jedes Kind hat einen Zettel mit einer Strichliste auf der Stirn und wird - weil erschöpft - nach einer einstellbaren Anzahl an Jobs getötet und durch ein neues ersetzt.

    Hilfreiche Befehle:

    
    > man httpd / apache / apache2 
    > #(Unter diesen drei Namen taucht der Server je nach OS auf - im folgenden "apache2")
    > ps -efH | grep apache2
    > apache2 -l
    > source /etc/apache2/envvars; apache2 -L