mixmastertobsi: CURL PHP Server "verabschiedet" sich

Hallo,

ich habe ein Problem mit CURL.

Ich lasse jede Minute ein PHP Skript laufen und "eigentlich" funktioniert das auch soweit. Das Skript dient dazu, um die Telefondaten vom externen Server zu laden und in die DB zu speichern. Wenn nun aber der externe Server nicht verfügbar, oder überlastet ist, bricht das Skript ab UND PHP verabschiedet sich komplett und ich muss es neustarten.

Dass das Skript nicht ausgeführt werden kann, ist nicht weiter schlimm, aber das sich der komplette Server verabschiedet, schon.

  1. Hallo,

    Wenn nun aber der externe Server nicht verfügbar, oder überlastet ist, bricht das Skript ab UND PHP verabschiedet sich komplett und ich muss es neustarten.

    Das klingt, als ob die Funktion die() statt einer Fehlerbehandlung verwendet wird.

    Gruß
    Kalk

    1. Hallo,

      nein - es wird kein die() verwendet und es wird ja auch kein Fehler ausgegeben.

      Ich konnte gerade noch etwas testen. Wenn ich die CURL einmal Abfrage, und es kein Zugriff zum externen Server gibt, passiert nichts. Wenn ich aber 3-4 Anfragen parallel starte, bricht das PHP ab.

      1. steht denn was im error.log des Servers?

        1. Leider gar nichts - das ist auch noch mein problem!

  2. Wenn nun aber der externe Server nicht verfügbar, oder überlastet ist, bricht das Skript ab UND PHP verabschiedet sich komplett

    Wie wird denn das PHP gestartet? CGI (wenn ja wie genau), Modul (welches Webservers), Linux, Windows. Welches PHP? Und wie wird das Skript gestartet? Cronjob?

    1. Wie wird denn das PHP gestartet?

      -> FPN, PHP 7.0, NGINX, Linux

      Und wie wird das Skript gestartet?

      Das Skript wird per AJAX im Browser alle 5 Sekungen aufgerufen. Ich vermute, dass es einfach zu viele parallele CURL Abfragen sind, die dann PHP zum erligen bringen, aber es kann ja nicht sein, dass da das ganze PHP abbricht und ich erst den Dienst neustarten muss.

      1. Und wie wird das Skript gestartet? Das Skript wird per AJAX im Browser alle 5 Sekungen aufgerufen.

        Je Minute hieß es weiter oben von Dir..

        den Dienst neustarten muss.

        Was fürn Dienst?

        MfG

        1. Hello,

          Und wie wird das Skript gestartet? Das Skript wird per AJAX im Browser alle 5 Sekungen aufgerufen.

          Je Minute hieß es weiter oben von Dir..

          Na, eine "Sekunge" ist doch ungefähr eine Minute ;-P

          Liebe Grüße
          Tom S.

          --
          Es gibt nichts Gutes, außer man tut es!
          Das Leben selbst ist der Sinn.
      2. Hello,

        Wie wird denn das PHP gestartet? -> FPN, PHP 7.0, NGINX, Linux

        FPN (?)
        Meinst Du FPM? Wenn Du Abkürzungen nur so hinschmeißt, kommt man als Leser, wenn man ehrlich ist, nicht wirklich mit. Wir Leser stehen in einem anderen momentanen Kontext, als Du!

        Ich nehme als mal an, dass Du folgenden Aufbau benutzt

        • Linux als Betriebssystem
        • NginX als Webserver
        • darin läuft ein FastCGI Process Manager
        • der stellt auf Request die PHP-Prozesse zur Verfügung

        Für PHP laufen also diverse zeitlich gestaffelte Einzelprozesse und die brechen irgendwann ab, wenn sie sich z. B. konkurrierend beeinträchtigen. Da könnte dann die maximale Skriptlaufzeit effektiv geworde sein?!

        Oder stürzt der NginX ab? Dein Linux läuft hoffentlich weiter?

        Du könntest also mal die Prozesstabelle bemühen und nachschauen, was nicht mehr läuft. Außerdem könntest Du von außen nach innen die Fehlermeldungen suchen. Als erstes also die Systemmeldugen des Linux (z. B. mit dmesg).

        Außerdem könntest Du deinen PHP-Prozessen beibringen, dass sie selber in ein Log schreiben. Beim Start die PID ins Log schreiben und beim Shutdown ebenfalls. Meistens klappt das noch.

        Danach sehen wir weiter.

        Soweit ich das aber bisher beurteilen kann, gibt es bei Dir keinen "PHP-Server" im Sinne von PHP-Prozess eigenständig dauerlaufen zu lassen.

        Liebe Grüße
        Tom S.

        --
        Es gibt nichts Gutes, außer man tut es!
        Das Leben selbst ist der Sinn.
      3. FPN, PHP 7.0, NGINX, Linux

        Das Skript wird per AJAX im Browser alle 5 Sekungen aufgerufen.

        Ganz einfach. Auch der NGINX kann nur eine bestimmte Anzahl an Prozessen (="laufenden Abrufe", Threads) verwalten.

        Wenn aller 5 Sekunden ein Skript aufgerufen wird, dass aber 10 Sekunden läuft, dann sieht das wie folgt aus:

        Sekunden | Prozesse gestartet | Prozesse beendet | laufende Prozesse 0.1 |1|0|1 5.1 |2|0|2 10.1 |3|1|2 15.1 |4|1|3 20.1 |5|2|3 25.1 |6|2|4

        Ergo erhöht sich die Anzahl der laufenden Prozesse stetig aller 10 Sekunden um einen und irgendwann will bzw. darf bzw. kann der NGINX nicht mehr, weil der einfach keinen weiteren Kindprozess mehr erstellen will bzw. darf bzw. kann, welcher die Anfrage entgegen nimmt.

        Im Error-Log steht nichts, weil der Webserver von den Verbindungsversuchen nicht mal was erfährt. Die "sterben" schon auf TCP-Ebene (OSI-Schicht 3). Allerdings hätte ein Blick in die Entwicklerkonsole des Browsers durchaus Klarheit verschaffen können.

        Ein anderer Webserver (Apache oder welcher auch immer) löst das Problem nicht, weil es bei den Voraussetzungen bleibt.

        Verstärken könnte den Effekt, dass mit der Anzahl der Threads oder Prozesse diese auch noch mehr Zeit für die Abarbeitung benötigen, weil der Prozessor diesen auch nur begrenzt "Zeitscheiben" zur Verfügung stellt. Also steigt ab dem Zeitpunkt, wo keine freien Prozessor-Threads zur Verfügung stehen, die Anzahl der Prozesse noch schneller an. Das kann und wird wohl noch dramatischer sein, wenn die Prozesse womöglich auf die Freigabe von Ressourcen, wie z.B. exklusiv gesperrten Dateien warten.

        Einzige Lösung:

        Die Dauer der Bearbeitung eines Abrufes (bisher 10 Sekunden) muss unter der des Intervalls (hier 5 Sekunden) liegen.

        Etwas wie htop oder ein wiederholtes ps ax | grep ngingx (ggf. mit Root-rechten in einem Terminal auf dem Server) dürfte Dir den Beweis liefern.

        1. Hi,

          Wenn aller 5 Sekunden ein Skript aufgerufen wird, dass aber 10 Sekunden läuft, dann sieht das wie folgt aus:

          Sekunden | Prozesse gestartet | Prozesse beendet | laufende Prozesse 0.1 |1|0|1 5.1 |2|0|2 10.1 |3|1|2 15.1 |4|1|3 20.1 |5|2|3 25.1 |6|2|4

          Zum Zeitpunkt 15.1 sind 2 Prozesse beendet - nämlich die, die um 0.0 und 5.0 gestarteten.

          Zum Zeitpunkt 20.1 sind 3 Prozesse beendet - die von 0.0, 5.0, 10.0

          usw.

          Sieht also eher so aus:

          Sekunden | Prozesse gestartet | Prozesse beendet | laufende Prozesse 0.1 |1|0|1 5.1 |2|0|2 10.1 |3|1|2 15.1 |4|2|2 20.1 |5|3|2 25.1 |6|4|2

          Ergo erhöht sich die Anzahl der laufenden Prozesse stetig aller 10 Sekunden

          nö. Die maximale Anzahl paralleler Prozesse ergibt sich unter der Bedingung "jeder Prozeß braucht n Sekunden" und "alle m Sekunden startet ein neuer Prozeß" aus (n/m + 1), hier 10/5 + 1 (das +1 kommt zum Tragen, wenn n nicht durch m teilbar ist)

          cu,
          Andreas a/k/a MudGuard

          1. Hello,

            nö. Die maximale Anzahl paralleler Prozesse ergibt sich unter der Bedingung [...]

            MMn ging es hier eher um die Problematik der sich überlappenden Prozesse und nicht wirklich um eine reale Laufzeit. Die müsste man dafür nämlich erst einmal kennen!

            Eine Formel, wie Du sie lieferst, ist auch nicht real nutzbar, weil jeder Prozess seine individuelle Laufzeit hat.

            Es wäre also viel wichtiger für den OP, seine Prozesse bezüglich der Laufzeit zu optimieren, vermutlich an erster Stelle auf konkurrierende Prozesse.

            Da gäbe es dann ja viele Möglichkeiten.

            Solange wir nicht den Code der betroffeneen Prozesse kennen, können wir keine verlässliche Aussage treffen!

            Liebe Grüße
            Tom S.

            --
            Es gibt nichts Gutes, außer man tut es!
            Das Leben selbst ist der Sinn.
            1. Eine Formel, wie Du sie lieferst, ist auch nicht real nutzbar, weil jeder Prozess seine individuelle Laufzeit hat.

              Mag sein. Es ging mir um eine Demonstration wie sich die Prozesse "aufschaukeln" und dass deren Zahl früher oder später gegen eine Mauer läuft. Bei genügender Beachtung von dem was auf "Verstärken könnte den Effekt, …" folgt sollte man auch darauf kommen, dass die Realität nicht in eine einfache Formel zu pressen ist.

              Die Fehlerbeschreibung weißt jedenfalls stark darauf hin, dass es sich um dieses Problem handelt. PHP stürzt hier nicht ab…

              Eine weitere Lösung:

              Der Abruf wird nicht alle n Sekunden gestartet sondern n Sekunden nach dem Ende des letzten Abrufes. Ich weiß nur nicht ob sich das mit der gestellten Aufgabe in Übereinstimmung bringen lässt. Falls nicht muss eben an der Leistungsfähigkeit des Servers "geschraubt" werden.

              Das Skript dient dazu, um die Telefondaten vom externen Server zu laden und in die DB zu speichern.

              Mir ist völlig unklar wieso hier ein Webserver notwendig sein soll und warum das nicht php-cli und ein cronjob können soll. Wenn man zuschauen will kann man mit ssh und tail -f auf das hoffentlich mitgeschriebene (und von logrotate behandelte!) Logfile glotzen. Oder halt nach jedem Durchlauf eine "Quittung" als statische Datei schreiben und die mit dem Browser aller paar Sekunden refreshen. Zudem sollte man mit ein wenig Mühe auch einen Weg finden, die Daten direkt vom "externen Server" in eine Datenbank schreiben zu lassen. Das dürfte den overhead, der hier offenbar im Abholen einer großen Textdatei besteht, gewaltig senken.

              1. Hello,

                Eine Formel, wie Du sie lieferst, ist auch nicht real nutzbar, weil jeder Prozess seine individuelle Laufzeit hat.

                Mag sein. Es ging mir um eine Demonstration wie sich die Prozesse "aufschaukeln" und dass deren Zahl früher oder später gegen eine Mauer läuft.

                Dich habe ich auch nicht gemeint. Dein Beispiel war gut! Deshalb auch (+).

                Ich habe @MudGuard gemeint. Man kann Dein Beispiel nicht plump in eine Formel packen, weil die viel zu komplex werden würde / von zu vielen Rahmenbedingungen abhängig wäre.

                Liebe Grüße
                Tom S.

                --
                Es gibt nichts Gutes, außer man tut es!
                Das Leben selbst ist der Sinn.
                1. Ich habe @MudGuard gemeint

                  Ich auch. Sorry, habe an der falschen Stelle geantwortet. Gut wäre ein Rückmeldung von "mixmastertobsi" ob sein Problem gelöst ist.