A maneira mais eficiente (tempo, custo) de raspar 5 milhões de páginas web?

8

Eu tenho uma lista de páginas da web que eu preciso para raspar, analisar e armazenar os dados resultantes em um banco de dados. O total é de cerca de 5.000.000.

Minha suposição atual da melhor maneira de abordar isso é implantar ~ 100 instâncias do EC2, fornecer a cada instância 50.000 páginas para raspar e, em seguida, deixar que a execução seja executada. Depois que o processo for concluído, mescle os bancos de dados. A suposição é que levaria cerca de um dia para ser executado (600ms para carregar, analisar e salvar cada página).

Alguém tem experiência em fazer um volume tão grande de captura de páginas em um tempo limitado? Já fiz grandes números antes (1.5m), mas isso foi de uma única máquina e demorei apenas uma semana para ser concluído.

O gargalo na minha situação é o download das páginas, a análise é algo que não leva mais de 2ms, então algo que pode agilizar o processo de baixar as páginas é o que eu estou procurando.

    
por sam 31.10.2011 / 11:31

2 respostas

7

Trabalhando no pressuposto de que o tempo de download (e, portanto, o uso da largura de banda) é o seu fator limitante, eu faria as seguintes sugestões:

Primeiramente, escolha instâncias de m1.large. Dos três 'níveis' de desempenho de E / S (que inclui largura de banda), as instâncias m1.large e m1.xlarge oferecem desempenho de E / S 'alto'. Como sua tarefa não está vinculada à CPU, a menos cara será a escolha preferida.

Em segundo lugar, sua instância poderá fazer downloads muito mais rápidos do que qualquer site pode veicular páginas - não faça o download de uma única página por vez em uma determinada instância, execute a tarefa simultaneamente - você deve conseguir pelo menos 20 páginas simultaneamente (embora, eu acho que você provavelmente pode fazer 50-100 sem dificuldade). (Tome o exemplo de baixar de um fórum do seu comentário - que é uma página dinâmica que vai levar o tempo do servidor para gerar - e há outros usuários usando essa largura de banda de sites, etc.). Continue a aumentar a simultaneidade até atingir os limites da largura de banda da instância. (Claro, não faça vários pedidos simultâneos para o mesmo site).

Se você realmente está tentando maximizar o desempenho, pode considerar o lançamento de instâncias em zonas geograficamente apropriadas para minimizar a latência (mas isso exigiria localizar geograficamente todos os seus URLs, o que pode não ser prático).

Uma coisa a notar é que a largura de banda da instância é variável, às vezes você obterá um desempenho mais alto e, em outras ocasiões, obterá um desempenho mais baixo. Nas instâncias menores, a variação no desempenho é mais significativa porque os links físicos são compartilhados por mais servidores e qualquer um deles pode diminuir sua largura de banda disponível. Entre as instâncias de m1.large, dentro da rede EC2 (mesma zona de disponibilidade), você deve se aproximar do rendimento teórico de gigabit.

Em geral, com a AWS, é quase sempre mais eficiente ir com uma instância maior em oposição a várias instâncias menores (a menos que você esteja olhando especificamente para algo como failover, etc., onde você precisa de várias instâncias).

Não sei o que a sua configuração implica, mas quando tentei anteriormente (entre 1 e 2 milhões de links, atualizados periodicamente), minha abordagem era manter um banco de dados dos links adicionando novos links à medida que eram encontrados, e processos de bifurcação para raspar e analisar as páginas. Uma URL seria recuperada (aleatoriamente) e marcada como em andamento no banco de dados, o script faria o download da página e, se obtivesse sucesso, marcaria a URL como baixada no banco de dados e enviaria o conteúdo para outro script que analisasse a página, novos links foram adicionados ao banco de dados como eles foram encontrados. A vantagem do banco de dados aqui era a centralização - vários scripts podiam consultar o banco de dados simultaneamente e (desde que as transações fossem atômicas) era possível garantir que cada página só seria baixada uma vez.

Alguns pontos adicionais de menção - há limites (acredito 20) no número de instâncias sob demanda que você pode ter em execução ao mesmo tempo - se você planeja exceder esses limites, será necessário solicitar à AWS para aumentar os limites da sua conta. Seria muito mais econômico para você executar instâncias spot e aumentar seus números quando o preço spot estivesse baixo (talvez uma instância sob demanda para manter tudo organizado e as instâncias spot restantes).

Se o tempo for de maior prioridade do que o custo para você, as instâncias de computação de cluster oferecem largura de banda de 10 Gbps - e devem render a maior largura de banda de download.

Recapitulação: experimente algumas instâncias grandes (em vez de pequenas instâncias) e execute vários downloads simultâneos em cada instância - adicione mais instâncias se você se limitar à largura de banda, mude para instâncias maiores se estiver com limite de CPU / memória. p>     

por 01.11.2011 / 19:39
4

Tentamos fazer algo semelhante e aqui estão meus 5 centavos:

  1. Obtenha 2-3 servidores baratos não monitorados, por exemplo não pague pela largura de banda.

  2. Use o python com o asyncore. A Asyncore é a maneira antiga de fazer as coisas, mas descobrimos que ela funciona mais rápido do que qualquer outro método. A desvantagem é que a pesquisa de DNS está bloqueando, ou seja, não é "paralela". Usando a sincronia, conseguimos arrastar URLs de 1M por 40 min, usando núcleos únicos de XEON 4, 8 GB de RAM. A média de carga no servidor foi menor que 4 (isso é excelente para 4 núcleos).

  3. Se você não gosta de assíncrona, tente o gevent. Ele até faz DNS não bloqueando. Usando o gevent, o 1M foi baixado por cerca de 50 minutos no mesmo hardware. A média de carga no servidor era enorme.

Note que testamos muitas bibliotecas Python, como greens, curl, liburl / liburl2, mas nós não testamos Twisted .

  1. Testamos o PHP + curl + vários processos, ele fez o trabalho por cerca de uma hora, mas a média de carga no servidor era enorme.
por 14.09.2013 / 18:28