Shopware 5 - Parallele Hochgeschwindigkeits-Miniaturbildererstellung

Insider Blog

Autor

Steckbrief

Veröffentlicht:

April 29, 2021

Kategorien:

Shopware

Tags:

VPN

Shopware 5 - Parallele Thumbnail-Generierung nach dem Verschieben eines Shopware 5-Systems auf einen anderen Server

Wir hatten einen Kunden mit 400k Bildern und 1600k Thumbnails, der von einem alten hdd-basierten Server auf einen neuen ssd-basierten umziehen musste. Das Problem war, dass der alte Server so langsam war, dass er bereits 2 Tage brauchte, um alle Bilder durchzuzählen, ganz zu schweigen vom Kopieren der Bilder.

Also haben wir beschlossen, nur die Originalbilder zu kopieren und die Thumbnails neu zu generieren. Um die Originalbilder zu kopieren, habe ich einen kleinen Konsolenbefehl erstellt, der alle Pfade der Originalbilder, die wir kopieren müssen, exportiert: ExportImagesCommand.php

Diese Dateiliste kann mit den Optionen tar -T oder rsync --files-from= verwendet werden, die diese Tools anweisen, nur die aufgelisteten Dateien zu verarbeiten. Für den anfänglichen Kopiervorgang ist tar sehr zu empfehlen, da es nur die aufgelisteten Dateien abholt, ohne irgendeine "Berechnung" wie bei rsync vorzunehmen.

SW5 Standard-Thumbnails generieren hätte 80 Stunden gedauert

... und würde nur die Hälfte eines Kerns nutzen.

Ich war neugierig, ob ich diesen Generierungsprozess beschleunigen kann. Der Server selbst hat 32 Kerne zur Verfügung, also habe ich den Befehl generate thumbnail aus sw5 kopiert und ihn so modifiziert, dass er mit dem Parameter --batch in Batches arbeitet:

ParallelThumbnailGenerateCommand.php

Damit es funktioniert, habe ich einfach den Shopware-Kern unter engine/Shopware/Models/Media/Repository.php geändert

Ich habe einfach die getAlbumMediaQuery Funktion geändert in:

public function getAlbumMediaQuery($albumId, $filter = null, $orderBy = null, $offset = null, $limit = null, $validTypes = null, $batch = null)
{
$builder = $this->getAlbumMediaQueryBuilder($albumId, $filter, $orderBy, $validTypes);
if (is_numeric($batch)) {
$builder->andWhere('MOD(media.id, 1000) = ?3');
$builder->setParameter(3, $batch);
}

    if ($limit !== null) {
        $builder->setFirstResult($offset)
                ->setMaxResults($limit);
    }

    return $builder->getQuery();
}

Es ist ein optionaler Parameter und wird nichts kaputt machen. Wenn man ein Shopware-Update durchführt, würde dies verschwinden, aber da ich auf der Suche nach einer einmaligen Aufgabe war, um die Dinge zu beschleunigen, habe ich es einfach im Kern geändert, anstatt eine langfristige Lösung zu finden.

Diese Funktion berechnet ein Modulo von 1000 auf der Medien-ID und vergleicht es mit der Chargen-ID. Wir haben also im Grunde 1000 Stapel zu verarbeiten, bis alle Arbeit erledigt ist.

Jetzt müssen wir nur noch alle 1000 Stapel parallel starten. Dazu habe ich das sehr hilfreiche Tool parallel verwendet, das unter Linux verfügbar ist:

Es startet 64 Batches parallel und setzt seine Arbeit fort, bis alle 1000 Batches fertig sind.

Und so sieht es bei htop aus:

parallel -j 64 ./bin/console my:image:generate:thumbnails --batch ::: {0..999}

Schließlich ist die ganze Arbeit jetzt in 3,5 Stunden statt in 80 Stunden erledigt.

Vorheriger Artikel
Für Entwickler, Für Shopbetreiber - Wir arbeiten nicht mit beliebigen Frameworks, Bibliotheken, Plugins und Programmiersprachen. Wir lieben es professionell. Software, die bei Helm & Walter entsteht, soll leistungsfähig und schlank sein. Hier unsere Favoriten: PHP (rekursives Akronym für PHP: Hypertext Preprocessor) ist eine weit verbreitete und für den …
June 27, 2017
Bernd Helm
Nächster Artikel
Wie man ausgewählte Domains über VPN unter Linux auflöst. In der heutigen Welt nutzen mehr Menschen als je zuvor VPN-Dienste, um aus der Ferne zu arbeiten. In manchen Fällen ist es jedoch nicht wünschenswert, den gesamten Datenverkehr und alle Domainnamenauflösungen über die VPN-Verbindung zu leiten.
April 21, 2022
Bernd Helm