Eu tenho uma lista de páginas da web que eu preciso raspar, analisar e depois armazenar os dados resultantes em um banco de dados. O total é de cerca de 5.000.000.
Minha suposição atual de que a melhor maneira de abordar isso é implantar ~ 100 instâncias do EC2, fornecer a cada instância 50.000 páginas para raspar e depois deixá-las em execução. Depois que o processo for concluído, mescle os bancos de dados. O pressuposto é que levaria cerca de um dia para ser executado (600 ms para carregar, analisar e salvar cada página).
Alguém tem experiência em fazer um volume tão grande de raspagem de página em tempo limitado? Já fiz grandes números antes (1,5 m), mas isso era de uma única máquina e demorou pouco mais de 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 que 2 ms, então algo que pode otimizar o processo de download das páginas é o que estou procurando.
fonte
Respostas:
Trabalhando na suposição de que o tempo de download (e, portanto, o uso da largura de banda) é seu fator limitador, eu faria as seguintes sugestões:
Primeiro, escolha instâncias 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 'alto' de E / S. Como sua tarefa não é vinculada à CPU, a menos cara delas será a escolha preferível.
Em segundo lugar, sua instância poderá fazer o download muito mais rapidamente do que qualquer site pode exibir páginas - não faça o download de uma única página de cada vez em uma determinada instância, execute a tarefa simultaneamente - você poderá fazer pelo menos 20 páginas simultaneamente (embora , Eu acho que você provavelmente pode fazer 50-100 sem dificuldade). (Pegue o exemplo do download de um fórum a partir do seu comentário - que é uma página dinâmica que levará tempo para o servidor gerar - e há outros usuários usando a largura de banda desses sites etc.). Continue aumentando a simultaneidade até atingir os limites da largura de banda da instância. (Obviamente, não faça várias solicitações simultâneas para o mesmo site).
Se você realmente está tentando maximizar o desempenho, considere iniciar instâncias em zonas geograficamente apropriadas para minimizar a latência (mas isso exigiria a localização geográfica de todos os seus URLs, o que pode não ser prático).
Uma coisa a observar é que a largura de banda da instância é variável, às vezes você obtém um desempenho mais alto e, outras vezes, obtém 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 a largura de banda disponível. Entre instâncias m1.large, dentro da rede EC2 (mesma zona de disponibilidade), você deve aproximar-se da taxa de transferência teórica de gigabits.
Em geral, com a AWS, é quase sempre mais eficiente usar uma instância maior do que 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 sua configuração implica, mas quando eu tentei isso anteriormente (entre 1 e 2 milhões de links, atualizado periodicamente), minha abordagem foi manter um banco de dados dos links, adicionando novos links à medida que foram encontrados e processando processos raspar e analisar as páginas. Um URL seria recuperado (aleatoriamente) e marcado como em andamento no banco de dados, o script baixaria a página e, se bem-sucedido, marcaria o URL como baixado 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 à medida que 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 fosse baixada apenas uma vez.
Alguns pontos adicionais de menção - existem limites (acredito 20) para o número de instâncias sob demanda que você pode executar em uma vez - se você planeja exceder esses limites, precisará solicitar à AWS que aumente sua conta limites. Seria muito mais econômico executar instâncias spot e aumentar seus números quando o preço spot for baixo (talvez uma instância sob demanda para manter tudo organizado e as instâncias spot restantes).
Se o tempo tiver uma prioridade mais alta do que o custo para você, as instâncias de computação do cluster oferecem largura de banda de 10 Gbps - e devem gerar a maior largura de banda de download.
Recapitulando: tente algumas instâncias grandes (em vez de muitas instâncias pequenas) e execute vários downloads simultâneos em cada instância - adicione mais instâncias se a largura de banda for limitada, vá para instâncias maiores se você estiver com CPU / memória ligada.
fonte
Tentamos fazer algo semelhante, e aqui estão meus 5 centavos:
Obtenha 2-3 servidores baratos e não medidos, por exemplo, não pague pela largura de banda.
Use python com asyncore. O Asyncore é a maneira antiga de fazer as coisas, mas descobrimos que 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 o asyncore, conseguimos raspar URLs de 1 milhão por 40 minutos, usando um único núcleo de XEON 4 e 8 GB de RAM. A média de carga no servidor foi menor que 4 (excelente para 4 núcleos).
Se você não gosta de asyncore, tente gevent. Ele ainda faz o DNS não bloquear. Usando o gevent, o 1M foi baixado por aproximadamente 50 min no mesmo hardware. A média de carga no servidor foi enorme.
Observe que testamos muitas bibliotecas Python, como grequests, curl, liburl / liburl2, mas não testamos o Twisted .
fonte