Existenz einer URL überprüfen - mit Timeout

Einklappen
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • Existenz einer URL überprüfen - mit Timeout

    Hallo Forum, ich brauche Hilfe.

    Ich habe mehrere Apache-Server die nur maximal zwei Clients gleichzeitig bedienen dürfen. Ich möchte auf einem extra Server per PHP eine Übersichtsseite darstellen, auf der der Benutzer erkennen kann, welcher der der Apache-Server momentan verfügbar, also nicht mit zwei Clients ausgelastet ist.
    Das ganze findet in einer LAN-Umgebung statt, wo viele Clients mehrere Gigabyte große Dateien per HTTP ziehen sollen.

    Das Problem ist: Wenn ein dritter Client (das PHP-Script) auf einen der ausgelasteten Apache-Server zugreifen möchte, wird dieser in die Warteschleife gelegt. Das Script hängt nun solange bis alle Apache-Server wieder frei sind, was den ganzen Sinn der Status-Übersichtsseite ja ad absurdum führt. Das Script soll anzeigen, welcher der Server gerade ausgelastet ist und welcher frei ist.

    Ich bin noch ein blutiger PHP-Anfänger und habe es bis jetzt mit diesen beiden Funktionen versucht:

    Diese Funktion öffnet eine kleine Text-Datei auf dem Sever und vergleicht ihren Inhalt mit einer vorgegebenen Variable.

    PHP-Code:
    function check($url$recip) {
        
    $arrText file($url);
        for (
    $i=0$i<count($arrText); $i++) {
            
    $text $text $arrText[$i];
        }
        if (
    eregi($recip$text)) {
            return 
    true;
        } else {
            return 
    false;
        } 
    Diese Funktion überprüft, ob eine bestimmte Datei existenz ist:

    PHP-Code:
    function check($url$maximumRedirections null
    $currentRedirection 0)
    {
       
    $result false;
       
    set_time_limit(3);
       
    $contents = @file_get_contents($url);
      
       
    // Check if we need to go somewhere else
      
       
    if (isset($contents) && is_string($contents))
       {
           
    preg_match_all('/<[\s]*meta[\s]*http-equiv="?REFRESH"?' 
    '[\s]*content="?[0-9]*;[\s]*URL[\s]*=[\s]*([^>"]*)"?' '[\s]*[\/]?[\s]*>
    /si'
    $contents$match);
          
           if (isset(
    $match) && is_array($match) && count($match) == 2
     
    && count($match[1]) == 1)
           {
               if (!isset(
    $maximumRedirections) ||
     
    $currentRedirection $maximumRedirections)
               {
                   return 
    getUrlContents($match[1][0],
     
    $maximumRedirections, ++$currentRedirection);
               }
              
               return 
    false;
           }
           else
           {
               return 
    true;
           }
       }
      
       


    Beide Funktionen lassen das Script hängen, wenn einer der Apache-Download-Server ausgelastet ist.

    Wie kann ich eine Timeout-Prüfung einbauen, welche die Funktion nach zwei Sekunden mit "return false;" beendet?

    oder:

    Wie kann ich Apache so konfigurieren, dass dem Client signalisiert, dass dieser sich in einer Warteschleife befindet?

    oder:

    Gibt es sonst irgendwelche Lösungen zur Realisierung dieser von mir angestrebten Status-Übersichtsseite?


    Ich wäre über jede Art der Hilfestellung erfreut und zutiefst dankbar.
    Den sachdienlichsten Hinweis würde ich auch gerne mit 15€ entlohnen (PayPal oder Überweisung).
    Zuletzt geändert von Stroganoff; 01.02.2006, 17:46.

  • #2
    http://www.php-resource.de/forum/sho...threadid=50454

    Kommentar


    • #3
      Statt file() besser fsockopen(), denn dieser Funktion kannst du einen Timeout mitgeben. http://php.net/fsockopen

      Aber ich würde es eher mit mod_status versuchen.
      Schau dir mal paar Beispiele an: http://www.google.com/search?q=%22Ap...+Status+for%22
      Also die Seite /server-status über einen Socket geholt, geparst und du weißt genau, wieviele Requests der Webserver gerade beantwortet. Wenn es wirklich so megagroße Dateien sind, wird sich das ja nicht so schnell ändern.

      Kommentar


      • #4
        fsockopen() ist schon funktionierender Bestandteil meines Scripts und checkt, ob die Server überhaupt online ist.

        Über mod_status bin ich nachdem ich diesen Thread geschrieben habe, auch schon gestolpert. Problematisch ist, dass die status-Seite nicht aufgerufen werden kann, wenn der Server gerade ausgelastet ist - der status-Request wird zu den anderen Clients in die Warteschleife gelegt.
        Es müsste also der Extra-Server, der die Übersicht bereitstellen sollen, eine ständige Verbindung zu den Download-Servern aufrechterhalten, so dass ich die MaxClients der Download-Server auf "3" stellen müsste, damit zwei Benutzer die Daten ziehen könnten.

        Ich bin mir aufgrund gewisser Unwissenheit nur gerade gar nicht im klaren darüber, wie ich das bewerkstelligen soll. Zudem laufen einige der Download-Server unter Windows.

        Kommentar


        • #5
          Problematisch ist, dass die status-Seite nicht aufgerufen werden kann, wenn der Server gerade ausgelastet ist - der status-Request wird zu den anderen Clients in die Warteschleife gelegt.
          Das heißt, du kannst nicht über den Webserver selbst prüfen, wie ausgelastet der Webserver ist, denn bei maximaler Auslastung, erfährst du es nicht.
          Dann schreibe dir ein Shellscript, dass ständig prüft, wieviele Apache-Prozesse laufen und das an einen zentralen Server sendet. (Klappt nur, wenn für jeden Request ein neuer Prozess gestartet und anschließend sofort wieder beendet wird.)

          Was machst du da überhaupt, wenn man fragen darf? Du betreibst mehrere Webserver, jeder auf 2 Requests beschränkt. Hast du einen load balancer davor geschaltet? Kannst du den nicht fragen, wie ausgelastet die einzelnen Webserver sind? Der muß es doch wissen (oder wenigstens gut schätzen).

          Kommentar


          • #6
            Ich habe keine Load-Balancer.
            Die Status-Überrsichtsseite dient gleichzeitig als Download-Portal. Für jede Datei gibt es pro Mirror einen Download-Button, welcher bei Page-Refresh ausgeblendet werden soll, falls der entsprechende Mirror ausgelastet ist. Das Load-Balancing übernimmt hier quasi der User.

            Mit dem Programmieren von Shell-Scripts hab ich leider noch weniger Plan, außerdem müssen ein paar der Download-Server unter Windows laufen.

            Könnte nicht auch der folgende Ansatz klappen?

            Auf dem Extra-Server, der die Status-Übersicht ausgeben soll, lasse ich per cron in sehr kurzen Abständen ein shellscript laufen, welches per wget von allen Download-Servern die URL http://hostname/server-status?auto in seperate Dateien anlegt (s1status, s2status etc.).
            Der Cronjob soll dermaßen schnell ablaufen, dass er immer wieder den selben "BusyServer" benutzt. Er müsste, laut meinen Überlegungen, seine Status-Datenbank schneller aktualisieren als die Timeout-Werte der Apache-Download-Server eingestellt sind.

            Diese Status-Dateien sehen wie folgt aus:

            Code:
            Total Accesses: 74
            Total kBytes: 84
            Uptime: 1005
            ReqPerSec: .0736318
            BytesPerSec: 85.5881
            BytesPerReq: 1162.38
            BusyServers: 1
            IdleServers: 1
            Scoreboard: [...]
            Jetzt müsste das PHP-Script der Übersichtsseite theoretisch nur noch den Wert hinter "Busy Servers:" auslesen und bei einem Wert größer als 2 die Status-Variable (bei mir $s1 ... $s9) auf false setzen.

            Wie ich bereits andeutete hab ich eigentlich keinen Plan von PHP, ich suche mir Scripts im Netz zusammen und frickeln daran herum. Momentan krieg ich's leider nicht gebacken, diese höchstwahrscheinlich triviale Funktion zu implementieren.

            Ich weiß, ich sollte mich hinsetzen und Bücher lesen - aber ich brauche einzig und allein diese Status-Abfrage, ich möchte keine komplette PHP-Seite bauen und ich hab nur noch eine Woche Zeit.
            Zuletzt geändert von Stroganoff; 01.02.2006, 18:58.

            Kommentar


            • #7
              Wenn ein Cronjob mit wget eine Resource von einem der Webserver bekommt, dann kannst du das auch mit file_get_contents bzw. fsockopen (wegen des Timeouts).

              Aber da steckt ein Denkfehler drin. Dazu ein Beispiel:

              Du hast drei Webserver: A und B sind Mirror, C als Portal.
              User öffnet Portalseite. Diese ist ein PHP-Script, welches schnell A/server-status und B/server-status liest und ggf. den Link ausblendet.

              Fall 1: Beide Server haben noch Luft.
              Portalseite bekommt von beiden die Antwort und blendet nichts aus. Perfekt.

              Fall 2: Mind. ein Server ist ausgelastet.
              Portalseite bekommt keine Antwort. wget würde in diesem Fall auch keine bekommen! (Denkfehler: wget ist auch nur ein Client.)

              Aber aus der Tatsache, dass du (in x Sekunden bis zum Timeout) keine Antwort bekommst, kannst du schließen, dass der Server ausgelastet ist und den Link ausblenden.

              So und nun nochmal komplett:
              Lege dir auf beide Server A und B eine leere Datei check.html
              Auf dem Portalserver brauchst du dann nur ein Script, dass mit fsockopen (und kurzem Timeout) versucht, von beiden Servern die Datei check.html zu laden. Klappt das, wird der Link zu diesem Mirror angezeigt, klappt das nicht (weil der Timeout zuschlägt), wird er ausgeblendet.

              Der Haken: User x bekommt beide Mirrors als frei angezeigt. User y ebenfalls. User x klickt auf A, dieser ist nun ausgelastet. User y erfährt davon nichts. Klickt y jetzt auch auf A, muß er warten.

              Zu diesem Problem gibt es keine korrekte Lösung. Man kann die Portalseite testen lassen, ob <Anzahl-gegenwärtiger-Portalseitenrequests> auf A und B frei sind, aber das ist immernoch fehleranfällig. Man kann <Anzahl...>*2 testen und wird damit wahrscheinlich immer gut fahren. Aber perfekt ist es nicht. Perfekt geht es nicht. Weil HTTP ... zustandslos ... und Portalseite ist nunmal nicht der Download selbst.
              Zuletzt geändert von onemorenerd; 01.02.2006, 19:15.

              Kommentar


              • #8
                Der Haken: User x bekommt beide Mirrors als frei angezeigt. User y ebenfalls. User x klickt auf A, dieser ist nun ausgelastet. User y erfährt davon nichts. Klickt y jetzt auch auf A, muß er warten.
                Das war mir sogar schon bewusst, ich halte das aber für kein Problem. Da wartet er halt und ist garantiert als nächster an der Reihe, oder er versucht halt einen anderen Link. Ich werde das Download-Portal mit einer entsprechenden Notiz versehen.

                Original geschrieben von onemorenerd
                So und nun nochmal komplett:
                Lege dir auf beide Server A und B eine leere Datei check.html
                Auf dem Portalserver brauchst du dann nur ein Script, dass mit fsockopen (und kurzem Timeout) versucht, von beiden Servern die Datei check.html zu laden. Klappt das, wird der Link zu diesem Mirror angezeigt, klappt das nicht (weil der Timeout zuschlägt), wird er ausgeblendet.
                Das hab ich ja schon versucht, aber ich kann mit fsockopen() nicht (oder weiß nicht, wie) direkt auf eine Datei des Servers zugreifen, hier ein kleines Test-Script:

                PHP-Code:
                $fp fsockopen("10.10.10.111"80$errno$errstr3);
                if (!
                $fp) { echo "ausgelastet"; } else { echo "funzt"; }

                echo 
                $fp
                Die Variable $fp; beinhaltet bei Verfügbarkeit und Auslastung immer die Angabe "Resource id #2". Wie ich mit fsockopen auf eine bestimmte Datei des Servers zugreifen soll, ist mir leider schleierhaft.

                Ich übersehe bestimmt was ganz klares und stehe womöglich nur noch eine einzige Antwort (incl. Code-Schnipsel?) von der Lösung entfernt.

                Kommentar


                • #9
                  Schau dir mal das erste Codebeispiel auf http://php.net/fsockopen an. Da wird ein GET-Request gesendet. Genau so kannst du es auch machen, aber bei dir "GET /check.html ..." statt "GET / ...".

                  OffTopic:
                  Da ich hier der einzige bin, stehen die 15 Euro wohl mir zu.
                  Ich verzichte darauf, kauf dir ein gutes Buch davon.

                  Kommentar


                  • #10
                    Der GET-Request wird mit der Funktion fputs() gesendet, welche offensichtlich über keine Timeout-Einstellung verfügt. Deswegen hängt das PHP-Script wieder ewig anstatt dem Benutzer eine Statusinfo zu geben.

                    Kommentar


                    • #11
                      Es hat sich erledigt.
                      Ich benutze nun wieder FTP für die Download-Server, nachdem ich endlich einen Windows-FTP-Server gefunden habe, der in der Lage ist, Dateien über 4GB zu verschicken.
                      Mein eigenes Script funktioniert mit FTP, da FTP bei Auslastung eine Fehlermeldung ausgibt, die das Script entsprechend verwerten kann, statt in der Apache-Queue hängen zu bleiben.

                      Entschuldigt bitte die Umstände.

                      Kommentar

                      Lädt...
                      X