2011-05-04 3 views
2

Nous utilisons PHP avec CodeIgniter pour importer des millions d'images à partir de centaines de sources, les redimensionnant localement, puis en téléchargeant la version redimensionnée sur Amazon S3. Le processus prend cependant beaucoup plus de temps que prévu, et nous cherchons des alternatives pour accélérer les choses. Pour plus de détails:Importer, redimensionner et télécharger des millions d'images sur Amazon S3

  • Une recherche est effectuée dans notre table de base de données MySQL pour les images qui n'ont pas encore été redimensionnées. Le résultat est un ensemble d'images.
  • Chaque image est importée individuellement à l'aide de cURL et temporairement hébergée sur notre serveur pendant le traitement. Ils sont importés localement car la bibliothèque n'autorise pas le redimensionnement/le rognage des images externes. Selon certains tests, la différence de vitesse lors de l'importation de différentes sources externes a été entre 80-140 secondes (pour l'ensemble du processus, en utilisant 200 images par test), de sorte que la source externe peut certainement ralentir les choses.
  • L'image actuelle est redimensionnée à l'aide du image_moo library, ce qui crée une copie de l'image
  • L'image redimensionnée est téléchargé sur Amazon S3 en utilisant un CodeIgniter S3 library
  • L'URL S3 pour la nouvelle image redimensionnée est ensuite enregistrée dans la base de données tableau, avant de commencer avec l'image suivante

Le processus prend 0,5 à 1 seconde par image, ce qui signifie que toutes les images actuelles prendraient un mois à redimensionner et à télécharger sur S3. Le problème majeur est que nous ajoutons constamment de nouvelles sources d'images, et nous prévoyons avoir au moins 30 à 50 millions d'images avant la fin de 2011, contre 4 millions au début du mois de mai.

J'ai remarqué une réponse dans StackOverflow qui pourrait être un bon complément à notre solution, où les images sont resized and uploaded on the fly, mais puisque nous ne voulons pas de retard inutile lorsque les gens visitent des pages, nous devons nous assurer que autant d'images que possible sont déjà téléchargés. En plus de cela, nous voulons des formats de tailles multiples des images, et actuellement seulement télécharger le plus important en raison de ce problème de vitesse. Idéalement, nous aurions au moins trois formats de taille (par exemple une vignette, une normale et une grande) pour chaque image importée. Quelqu'un a suggéré de faire des transferts groupés vers S3 il y a quelques jours - toute expérience sur les économies que cela pourrait représenter serait utile.

Les réponses à n'importe quelle partie de la question seraient utiles si vous avez une certaine expérience du processus semblable. Une partie du code (simplifié)

$newpic=$picloc.'-'.$width.'x'.$height.'.jpg'; 
$pic = $this->image_moo 
     ->load($picloc.'.jpg') 
    ->resize($width,$height,TRUE) 
    ->save($newpic,'jpg'); 
if ($this->image_moo->errors) { 
    // Do stuff if something goes wrong, for example if image no longer exists - this doesn't happen very often so is not a great concern 
} 
else { 
     if (S3::putObject(
     S3::inputFile($newpic), 
     'someplace', 
     str_replace('./upload/','', $newpic), 
     S3::ACL_PUBLIC_READ, 
     array(), 
     array( 
     "Content-Type" => "image/jpeg", 
    ))) 
{ // save URL to resized image in database, unlink files etc, then start next image 
+0

Vous pouvez tirer parti de l'expérience d'Etsy dans le traitement par lots de millions d'images. Voir: https://codeascraft.com/2010/07/09/batch-processing-millions-of-images/ – EdgeCaseBerg

Répondre

3

Pourquoi ne pas ajouter une logique d'emballage qui vous permet de définir des plages ou des groupes d'images et puis exécutez le script plusieurs fois sur le serveur. Si vous pouvez avoir quatre de ces processus en cours d'exécution en même temps sur différents ensembles d'images, il finira quatre fois plus vite!

Si vous êtes coincé à essayer de passer à travers un carnet de commandes très grand au moment où vous pouvez regarder tourner quelques instances Amazon EC2 et les utiliser pour paralléliser davantage le processus.

+1

Je suis d'accord. Il doit y avoir un moyen de scinder le problème où vous pouvez paralléliser le traitement. Les instances EC2 semblent être une idée solide. Une sorte de concept de map/reduce-type fonctionnera ici. –

1

Je vous suggère de diviser votre script en 2 scripts qui s'exécutent simultanément. On chercherait des images distantes à une source locale, simplement pour toutes les images qui n'ont pas encore été traitées ou mises en cache localement. Étant donné que les sources distantes ajoutent un peu de délai à vos demandes, vous aurez la possibilité de récupérer en permanence des images distantes, et pas seulement lorsque vous les traiterez.

Simultanément, vous utilisez un deuxième script pour redimensionner les images mises en cache localement et les télécharger sur Amazon S3.Alternativement, vous pouvez également diviser cette partie du processus en utilisant un script pour le redimensionnement dans un fichier local puis un autre pour télécharger les fichiers redimensionnés vers S3.

La première partie (extraction de l'image source distante) bénéficierait grandement de l'exécution de plusieurs instances simultanées comme James C suggère ci-dessus.