Performance beim Kopieren von Dateien zwischen zwei Servern

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

  • Performance beim Kopieren von Dateien zwischen zwei Servern

    Guten Morgen,

    ohne großartiges Geschwafel sofort zu meinem Problem. Ich lese mittels XMLReader eine XML Datei (im Schnitt ca. 8 MB groß / 2500 Datensätze) ein, in der sich neben anderen Daten auch URLs zu Bildern auf entfernten Servern befinden. Diese URLs werden mittels curl vom entfernten Server auf den Server kopiert, auf dem das Script läuft. Jedes Bild hat eine durchschnittliche Dateigröße von 20KB.

    Das Kopieren der Bilder zwischen den Servern dauert nun einige Zeit und zwingt den Server irgendwie in die Knie, wenn noch andere User auf dem Server aktiv sind. Erfolgreich importierte Bilder werden nachträglich auch noch per GDLib in verschiedene Bildmaße umgerechnet, sofern man einen Datensatz im Frontend zur Anzeige aufruft, für den die runtergerechneten Thumbnails noch nicht existieren.

    Meine Frage wäre, ob es schneller arbeitende Möglichkeiten mit PHP gibt? Momentan setze ich auf curl, da ich hier verschiedene Optionen wie das Timeout festlegen kann. Das erschien mir bis hierhin sinnvoll.

    Also, gibt es schnellere Möglichkeiten?
    MM Newmedia | MeinBlog

  • #2
    Du könntest die Bilder nicht „per se“ herunterladen, sondern nur dann, wenn sie gebraucht werden.

    Also per Rewriting ein Script starten, dass für nicht auf der Platte gefundene Bilder den HTTP-Request an den entfernten Server macht, nur für dieses eine Bild, es auf die nötigen Maße verkleinert und dann im Cache ablegt.

    Damit muss natürlich der Nutzer, der dieses Bild als erstes ansehen will, dann dafür ein kleines bisschen Wartezeit in Kauf nehmen.
    I don't believe in rebirth. Actually, I never did in my whole lives.

    Kommentar


    • #3
      Speicherauslastung schon mal beobachtet? Evtl. hält dein Script die abgeholten Dateien im Speicher? Sollte das der Fall sein, lässt sich das beheben.

      Ansonsten ist @wahsagas "on-demand"-Ansatz natürlich zu überlegen, ausser es gibt anderweitige Gründe, die das generelle Vorhalten der Bilder auf deinem Server erfordern.
      Ihr habt ein Torturial durchgearbeitet, das auf den mysql_-Funktionen aufbaut?
      Schön - etwas Geschichte kann ja nicht schaden.
      Aber jetzt seht euch bitte php.net/pdo oder php.net/mysqli bevor ihr beginnt!

      Kommentar


      • #4
        Also Wahsaga's on demand Ansatz wird zum Teil schon umgesetzt. Es wird momentan nur das Original Bild beim Import kopiert. Auf das Kopieren der Bilder während des Imports komplett zu verzichten wäre natürlich eine Idee. So könnte man die importierten Datensätze mit einem pending Flag versehen. Später würde dann ein Cron Job in regelmäßigen mit der Serverlast zu vereinbarenden Abständen die Bilder für die Datensätze einrichten.

        Wegen dem Speicherverbrauch habe ich gerade auch gelesen, dass curl hier vor PHP 5.3 ein Problem hat. Allerdings werden die ermittelten Bilder gar nicht in den Speicher gelesen. Zumindest gehe ich davon aus, da eine gültige Stream Resource beim curl Aufruf mit übergeben wird, so dass die erhaltenen Daten direkt als Datei auf dem Server abgelegt werden.

        Beispiel:
        PHP-Code:
        // Download via. cURL
        $ch curl_init($urlZurQuelldatei);
        $fp fopen($pfadZurSchreibendenDatei"wb");
            
        $options = array(
            
        CURLOPT_FILE => $fp,
            
        CURLOPT_HEADER => 0,
            
        CURLOPT_FOLLOWLOCATION => 0,
            
        CURLOPT_TIMEOUT => 60
        );
            
        curl_setopt_array($ch$options);
        $result curl_exec($ch);
            
        curl_close($ch);
        fclose($fp); 
        Da das Einlesen per XMLReader auch per Stream geschieht und das Schreiben der kopierten Dateien eben auch direkt in eine Datei stattfindet, frage ich mich gerade, wo der großartige Speicherverbrauch liegen soll? Das Script hält die Daten ja gar nicht im Speicher, wegen der Streams. Oder habe ich bezüglich der Streams etwas falsch verstanden? Blöd, dass ich keinen Einblick in die Server Logs habe.
        MM Newmedia | MeinBlog

        Kommentar


        • #5
          Wenn du die Bilder nach dem Download nicht in PHP einliest/weiterverarbeitest, dann liegt die Performancebremse möglicherweise auch nicht unbedingt an der Stelle - auch wenn man es nicht vollständig ausschließen kann.

          Wie XML-Reader arbeitet weiß ich nicht genau, aber möglicherweise geht hier schon sehr viel Speicher drauf, wenn das XML-File aus sehr vielen Knoten besteht - zumindest in DOM kann ein relativ kleines XML fertig geparst im Speicher schon ganz schön was belegen.

          Allerdings muss der Einbruch auch gar nicht durch ausgehenden Ram-Speicher bedingt sein. Mit den Standardwerten in einer php.ini und vernünftig konfiguriertem Webserver solltest du sowieso eher eine Fehlermeldung bekommen, dass du das Memory-Limit für PHP überschritten hast.

          Denkbar wäre auch, dass die Webserverkonfiguration der Knackpunkt ist. Ein niedriger MaxServer-Wert in Kombination mit einer unnötig hohen Keep-Alive Einstellung (und vielleicht noch mit wenigen Max-Keepalive-Requests) kann auch schnell dafür sorgen, dass es zu Wartezeiten kommt obwohl die Hardware mehr als genug Kapazitäten hätte.

          ... das führt mich jetzt grade zu folgender Frage:
          Läuft das Script überhaupt über den Webserver? Oder reden wir hier von einem Cronjob, der PHP auf CLI-Ebene ausführt?
          Ihr habt ein Torturial durchgearbeitet, das auf den mysql_-Funktionen aufbaut?
          Schön - etwas Geschichte kann ja nicht schaden.
          Aber jetzt seht euch bitte php.net/pdo oder php.net/mysqli bevor ihr beginnt!

          Kommentar


          • #6
            Zitat von Quetschi Beitrag anzeigen
            Wenn du die Bilder nach dem Download nicht in PHP einliest/weiterverarbeitest, dann liegt die Performancebremse möglicherweise auch nicht unbedingt an der Stelle - auch wenn man es nicht vollständig ausschließen kann.
            Im Moment ist es noch so, dass die Bilder während des Imports vom entfernten Server auf den Server kopiert werden, auf dem das Script läuft. Genau hier liegt auch die Last. Lasse ich das Script ohne das Kopieren der Bilder laufen, werden die XML Daten relativ zügig eingelesen.

            Wie XML-Reader arbeitet weiß ich nicht genau, aber möglicherweise geht hier schon sehr viel Speicher drauf, wenn das XML-File aus sehr vielen Knoten besteht - zumindest in DOM kann ein relativ kleines XML fertig geparst im Speicher schon ganz schön was belegen.
            Das XMLReader Objekt arbeitet als Stream und hat entgegen DomDocument und SimpleXML niemals das komplette XML Konstrukt im Speicher. Es wird lediglich der aktuelle Knoten im Speicher belassen. XMLReader arbeitet sehr viel performanter und schneller als DomDocument, SimpleXML und SAX.

            ... das führt mich jetzt grade zu folgender Frage:
            Läuft das Script überhaupt über den Webserver? Oder reden wir hier von einem Cronjob, der PHP auf CLI-Ebene ausführt?
            Es handelt sich hier wirklich um ein Script, welches auf dem Webserver läuft. Ein User lädt die XML Datei per Datei Upload auf den Server. Sobald die Datei auf dem Server liegt, wird diese mit XMLReader gelesen und verarbeitet.

            Ich tippe hier auch auf irgendeinen Knackpunkt in der Serverkonfiguration. Selbst wenn ich das PHP memory_limit auf 1GB setze und die max_execution_time ausschalte, bricht der Import mit den Bildern ohne PHP Fehlermeldung ab. Mal läuft's 'ne viertel Stunde gut. Mal eine halbe Stunde. Aber dann ist Ende.
            MM Newmedia | MeinBlog

            Kommentar


            • #7
              Du könntest einen kleinen Logger schreiben, den du an relevanten Punkten deines Scripts einbaust um mal die Speichernutzung von PHP während der jeweiligen Arbeitschritte mitzuschreiben.

              Weiterhin einfach auch die Prozessorauslastung beobachten, schauen ob während des Performanceeinbruchs noch freie Webserver-Prozesse da sind und auch schauen ob vielleicht einfach das Netzwerk ausgelastet ist.

              Hast du das Script schon mal von der Kommandozeile aus gestartet?
              Ihr habt ein Torturial durchgearbeitet, das auf den mysql_-Funktionen aufbaut?
              Schön - etwas Geschichte kann ja nicht schaden.
              Aber jetzt seht euch bitte php.net/pdo oder php.net/mysqli bevor ihr beginnt!

              Kommentar

              Lädt...
              X