1

Mon objectif est de construire un robot d'exploration distribué qui traite plus d'un site Web à la fois et plus d'une requête également. Pour cela, j'ai construit un robot d'indexation en Python en utilisant des paquets standards comme 'requests' et 'BeautifulSoup'. Ça fonctionne bien. Afin de le distribuer, j'ai utilisé rabbitMQ. Cela me permet de rendre le système plus rapide en ayant plus d'un processus aidant l'exploration.Calcul distribué en Python - Web crawler

Mon système fonctionne dans un modèle workpool:

  • J'ai un serveur principal de recevoir les requêtes et le démarrage d'une nouvelle analyse pour chacun d'eux. Au démarrage de l'analyse, certaines URL sont collectées en entrant la requête dans un moteur de recherche.
  • A partir de maintenant, le serveur principal envoie les URL aux processus/travailleurs disponibles avec rabbitMQ et attend de recevoir plus d'URL de leur part.

Cependant, j'ai un goulot d'étranglement énorme dans cette architecture, et ce n'est pas le serveur principal ... rabbitmq ne me permet pas de consommer plus de 1 message à la fois la fonction (channel.basic_qos() ne fonctionne pas travail!). Ce que je voulais était d'avoir une file d'attente privée pour chaque requête (comme je l'ai maintenant) et être capable de traiter ces 2 requêtes en même temps, aussi vite que possible. Par ce moyen, parallélisez le code des travailleurs afin qu'il puisse traiter le nombre maximum d'urls, au lieu de 1 url à la fois.

Que dois-je utiliser pour remplacer rabbitMQ ici? J'ai spécifiquement atteint les développeurs de rabbitMQ et je ne peux pas en faire ce que je veux, alors j'essaie de trouver un 'package de distribution' différent. peut-être Kafka?

Répondre

0

D'abord, vous devrez déterminer quelles sont les limites de votre programme. Est-ce que I/O est lié ou CPU lié?

E.g. Si une simple version non parallèle de votre programme peut saturer votre connexion réseau, il est inutile de faire une version parallèle.

Pour un robot d'indexation Web, le réseau constitue souvent le goulot d'étranglement ultime. Mais supposons que vous ayez une capacité réseau suffisante. Dans ce cas, je suggère d'utiliser un multiprocessing.Pool. La fonction qui agit en tant que processus de travail prend une URL en entrée et renvoie les données traitées à partir de l'URL. Vous créez un pool et utilisez la méthode imap_unordered pour appliquer les fonctions de travail à une liste d'URL;

def worker(url): 
    rv = requests.get(url) 
    # Do whatever processing is needed. 
    result = ... 
    return (url, result) 

urls = ['www.foo.com', ...] 
p = multiprocessing.Pool() 
for url, result in p.imap_unordered(worker, urls): 
    print('The URL ', url, 'returned ', result) 

Par défaut, le Pool utilisera autant de travailleurs que la CPU a noyaux. L'utilisation de plus de travailleurs n'est généralement pas utile.

Notez que la valeur renvoyée par le worker doit être renvoyée du processus de travail au processus parent. Donc, il doit être pickle-capable. Si vous devez renvoyer une énorme quantité de données, cela peut devenir un goulot d'étranglement IPC. Dans ce cas, il est probablement préférable de l'écrire par ex. un système de fichiers basé sur RAM et juste retourner le nom de fichier pour le fichier de données.

+0

Merci pour votre réponse. Le multitraitement est certainement une idée pour la parallélisation. Cependant, comme je l'ai dit, j'utilise rabbitmq pour rendre l'analyse distribuée (de nombreux ordinateurs/processus peuvent se joindre) et c'est ce qui me cause le goulot d'étranglement. – Skinishh