Le moyen le plus efficace (temps, coût) de gratter 5 millions de pages Web?

8

J'ai une liste de pages Web dont j'ai besoin pour gratter, analyser puis stocker les données résultantes dans une base de données. Le total est d'environ 5 000 000.

Mon hypothèse actuelle sur la meilleure façon d'aborder cela est de déployer ~ 100 instances EC2, de fournir à chaque instance 50 000 pages à gratter, puis de laisser cela s'exécuter, puis une fois le processus terminé, fusionnez les bases de données. L'hypothèse est que cela prendrait environ une journée pour s'exécuter (600 ms pour charger, analyser et enregistrer chaque page).

Quelqu'un a-t-il de l'expérience avec un tel volume de grattage de pages dans un temps limité? J'ai déjà fait de grands nombres (1,5 m) mais c'était à partir d'une seule machine et j'ai pris un peu plus d'une semaine pour terminer.

Le goulot d'étranglement dans ma situation est le téléchargement des pages, l'analyse est quelque chose qui ne prend pas plus de 2 ms, donc quelque chose qui peut rationaliser le processus de téléchargement des pages est ce que je recherche.

sam
la source
Lorsque vous dites une liste de pages Web, s'agit-il simplement d'une page Web ordinaire ou de sites entiers comme un forum ou quelque chose? Aussi, même si vous allez à fond, y a-t-il des règles en place pour les sites que vous souhaitez gratter (ou est-ce que cela met d'abord la théorie en place?)
tombull89
J'ai plusieurs cas où cette réponse est pertinente pour moi, pour la question, j'ai donné un chiffre arbitraire qui pourrait facilement être visualisé et le type de page Web varie, mais pour la question, on peut supposer que c'est un forum en train d'être gratté si tu veux. Que le site autorise ou non le grattage n'est pas un problème (pour la question de toute façon)
sam
Pour clarifier le point sur le type de pages Web: chaque page Web est indépendante des autres, elles peuvent être grattées dans n'importe quel ordre et ne dépendent pas d'une autre grattée. Cela pourrait être fait en avant, en arrière, au hasard, cela n'a pas d'importance.
sam
Je vois. Je ne sais pas comment EC2 gérerait les téléchargements, mais certains utilisateurs SF plus expérimentés peuvent avoir des idées. En outre, hors sujet, mais est-ce le citricsquid des MinecraftForums? C'est un nom assez ... unique.
tombull89
mmhmm c'est moi.
sam

Réponses:

7

En supposant que le temps de téléchargement (et donc l'utilisation de la bande passante) est votre facteur limitant, je ferais les suggestions suivantes:

Tout d'abord, choisissez les instances m1.large. Des trois «niveaux» de performances d'E / S (qui incluent la bande passante), les instances m1.large et m1.xlarge offrent toutes deux des performances d'E / S «élevées». Étant donné que votre tâche n'est pas liée au processeur, le moins cher d'entre eux sera le choix préférable.

Deuxièmement, votre instance pourra télécharger beaucoup plus rapidement que n'importe quel site peut servir des pages - ne téléchargez pas une seule page à la fois sur une instance donnée, exécutez la tâche simultanément - vous devriez pouvoir faire au moins 20 pages simultanément (bien que , Je suppose que vous pouvez probablement faire 50-100 sans difficulté). (Prenez l'exemple du téléchargement à partir d'un forum à partir de votre commentaire - c'est une page dynamique qui va prendre du temps au serveur à générer - et d'autres utilisateurs utilisent la bande passante de ce site, etc.). Continuez à augmenter la simultanéité jusqu'à ce que vous atteigniez les limites de la bande passante de l'instance. (Bien sûr, ne faites pas plusieurs demandes simultanées au même site).

Si vous essayez vraiment de maximiser les performances, vous pouvez envisager de lancer des instances dans des zones géographiquement appropriées pour minimiser la latence (mais cela nécessiterait de géolocaliser toutes vos URL, ce qui peut ne pas être pratique).

Une chose à noter est que la bande passante de l'instance est variable, parfois vous obtiendrez des performances plus élevées et d'autres fois vous obtiendrez des performances plus faibles. Sur les instances plus petites, la variation des performances est plus importante car les liaisons physiques sont partagées par plusieurs serveurs et n'importe lequel d'entre eux peut réduire votre bande passante disponible. Entre les instances m1.large, au sein du réseau EC2 (même zone de disponibilité), vous devriez obtenir un débit gigabit théorique proche.

En général, avec AWS, il est presque toujours plus efficace d'utiliser une instance plus grande que plusieurs instances plus petites (sauf si vous examinez spécifiquement quelque chose comme le basculement, etc. où vous avez besoin de plusieurs instances).

Je ne sais pas ce que votre configuration implique, mais quand j'ai déjà tenté cela (entre 1 et 2 millions de liens, mis à jour périodiquement), mon approche était de maintenir une base de données des liens en ajoutant de nouveaux liens tels qu'ils ont été trouvés et en forçant les processus pour gratter et analyser les pages. Une URL serait récupérée (au hasard) et marquée comme en cours sur la base de données, le script téléchargerait la page et en cas de succès, marquerait l'url comme téléchargée dans la base de données et enverrait le contenu à un autre script qui analysait la page, de nouveaux liens ont été ajoutés à la base de données au fur et à mesure de leur découverte. L'avantage de la base de données ici était la centralisation - plusieurs scripts pouvaient interroger la base de données simultanément et (tant que les transactions étaient atomiques), on pouvait être sûr que chaque page ne serait téléchargée qu'une seule fois.

Quelques points supplémentaires à mentionner - il y a des limites (je crois 20) sur le nombre d'instances à la demande que vous pouvez avoir en même temps - si vous prévoyez de dépasser ces limites, vous devrez demander à AWS d'augmenter votre compte. limites. Il serait beaucoup plus économique pour vous d'exécuter des instances ponctuelles et d'augmenter vos nombres lorsque le prix au comptant est bas (peut-être une instance à la demande pour tout organiser et les autres instances ponctuelles).

Si le temps est plus prioritaire que le coût pour vous, les instances de calcul de cluster offrent une bande passante de 10 Gbit / s et devraient fournir la plus grande bande passante de téléchargement.

Récapitulatif: essayez quelques grandes instances (au lieu de nombreuses petites instances) et exécutez plusieurs téléchargements simultanés sur chaque instance - ajoutez plus d'instances si la bande passante est limitée, passez à des instances plus grandes si vous vous trouvez lié à la CPU / mémoire.

cyberx86
la source
4

Nous avons essayé de faire quelque chose de similaire, et voici mes 5 cents:

  1. Obtenez 2-3 serveurs non mesurés bon marché, par exemple, ne payez pas pour la bande passante.

  2. Utilisez python avec asyncore. Asyncore est l'ancienne façon de faire les choses, mais nous avons constaté que cela fonctionne plus rapidement que toute autre méthode. L'inconvénient est que la recherche DNS est bloquante, c'est-à-dire non "parallèle". En utilisant asyncore, nous avons réussi à gratter 1M d'URL pendant 40 min, en utilisant des cœurs XEON 4 simples, 8 Go de RAM. La charge moyenne sur le serveur était inférieure à 4 (ce qui est excellent pour 4 cœurs).

  3. Si vous n'aimez pas asyncore, essayez gevent. Il fait même du DNS non bloquant. En utilisant gevent, 1M a été téléchargé pendant environ 50 minutes sur le même matériel. La charge moyenne sur le serveur était énorme.

Notez que nous avons testé de nombreuses bibliothèques Python, telles que grequests, curl, liburl / liburl2, mais nous n'avons pas testé Twisted .

  1. Nous avons testé PHP + curl + plusieurs processus, il a fait le travail pendant environ une heure, mais la charge moyenne sur le serveur était énorme.
pseudo
la source
«Sans mesure» signifie généralement «nous vous fermons quand nous en avons envie», selon mon expérience.
ceejayoz
d'après mon expérience, "non mesuré" signifie plafonné à 100 Mbits environ
Nick