Cara (waktu, biaya) paling efisien untuk mengikis 5 juta halaman web?

8

Saya memiliki daftar halaman web yang perlu saya gesek, parsing dan kemudian menyimpan data yang dihasilkan dalam database. Totalnya sekitar 5.000.000.

Asumsi saya saat ini tentang cara terbaik untuk mendekati ini adalah dengan menyebarkan ~ 100 instance EC2, berikan setiap instance dengan 50.000 halaman untuk dikikis dan kemudian biarkan dijalankan, lalu setelah proses selesai menggabungkan database bersama. Asumsinya adalah itu akan memakan waktu sekitar satu hari untuk berjalan (600ms untuk memuat, mengurai dan menyimpan setiap halaman).

Adakah yang punya pengalaman dalam melakukan pengikisan halaman dalam jumlah besar dalam waktu yang terbatas? Saya telah melakukan sejumlah besar sebelumnya (1,5m) tetapi itu dari satu mesin dan hanya membutuhkan waktu lebih dari seminggu untuk menyelesaikannya.

Hambatan dalam situasi saya adalah pengunduhan halaman, penguraian adalah sesuatu yang membutuhkan waktu tidak lebih dari 2 ms, jadi sesuatu yang dapat merampingkan proses mengunduh halaman adalah apa yang saya cari.

sam
sumber
Ketika Anda mengatakan daftar halaman web, apakah ini hanya halaman web biasa atau seluruh situs seperti forum atau sesuatu? Juga, bahkan jika Anda keluar datar, apakah ada aturan di tempat untuk situs yang ingin Anda gesek (atau ini hanya mendapatkan teori di tempat pertama?)
tombull89
Saya memiliki beberapa contoh di mana jawaban ini relevan bagi saya, untuk pertanyaan yang saya berikan angka yang sewenang-wenang yang dapat dengan mudah divisualisasikan dan jenis halaman web bervariasi, tetapi untuk pertanyaan dapat diasumsikan itu adalah forum yang sedang dikikis jika kamu suka. Apakah situs tersebut memungkinkan pengikisan atau tidak adalah masalah (untuk pertanyaannya)
sam
Untuk memperjelas poin tentang jenis halaman web: setiap halaman web terpisah dari yang lain, mereka dapat dikikis dalam urutan apa pun dan tidak bergantung pada yang lain yang dikikis. Itu bisa dilakukan ke depan, ke belakang, secara acak, itu tidak masalah.
sam
Saya melihat. Saya tidak tahu bagaimana EC2 akan menangani unduhan, tetapi beberapa pengguna SF yang lebih berpengalaman mungkin memiliki beberapa ide. Juga, off-topic, tapi apakah ini yang citricsquid dari MinecraftForums? Itu cukup ... unik ... nama.
tombull89
mmhmm yaitu I.
sam

Jawaban:

7

Bekerja dengan asumsi bahwa waktu pengunduhan (dan karenanya penggunaan bandwidth) adalah faktor pembatas Anda, saya akan membuat saran berikut:

Pertama, pilih m1.large instances. Dari tiga 'level' kinerja I / O (yang termasuk bandwidth), instance m1.large dan m1.xlarge keduanya menawarkan kinerja I / O 'tinggi'. Karena tugas Anda tidak terikat CPU, yang paling murah di antaranya akan menjadi pilihan yang lebih disukai.

Kedua, instance Anda akan dapat mengunduh jauh lebih cepat daripada situs mana pun dapat melayani halaman - jangan mengunduh satu halaman sekaligus pada contoh yang diberikan, jalankan tugas secara bersamaan - Anda harus dapat melakukan setidaknya 20 halaman secara bersamaan (walaupun , Saya kira Anda mungkin dapat melakukan 50-100 tanpa kesulitan). (Ambil contoh pengunduhan dari forum dari komentar Anda - itu adalah halaman dinamis yang akan mengambil waktu server untuk menghasilkan - dan ada pengguna lain yang menggunakan bandwidth situs, dll.). Terus tingkatkan konkurensi hingga Anda mencapai batas bandwidth instance. (Tentu saja, jangan membuat beberapa permintaan secara bersamaan ke situs yang sama).

Jika Anda benar-benar mencoba memaksimalkan kinerja, Anda dapat mempertimbangkan untuk meluncurkan instance di zona yang sesuai secara geografis untuk meminimalkan latensi (tetapi itu akan mensyaratkan geolokasi semua URL Anda, yang mungkin tidak praktis).

Satu hal yang perlu diperhatikan adalah bahwa bandwidth misalnya adalah variabel, kadang-kadang Anda akan mendapatkan kinerja yang lebih tinggi, dan pada saat lain Anda akan mendapatkan kinerja yang lebih rendah. Pada contoh yang lebih kecil, variasi dalam kinerja lebih signifikan karena tautan fisik dibagi oleh lebih banyak server dan yang mana saja dapat mengurangi bandwidth yang tersedia. Antara instance m1.large, dalam jaringan EC2 (zona ketersediaan yang sama), Anda harus mendekati throughput gigabit teoretis.

Secara umum, dengan AWS, hampir selalu lebih efisien untuk menggunakan instance yang lebih besar sebagai lawan dari beberapa instance yang lebih kecil (kecuali Anda secara khusus melihat sesuatu seperti failover, dll. Di mana Anda memerlukan banyak instance).

Saya tidak tahu apa yang dibutuhkan oleh pengaturan Anda, tetapi ketika saya sebelumnya telah mencoba ini (antara 1 dan 2 juta tautan, diperbarui secara berkala), pendekatan saya adalah mempertahankan basis data tautan yang menambahkan tautan baru saat ditemukan, dan proses forking untuk mengikis dan mengurai halaman. Sebuah URL akan diambil (secara acak) dan ditandai sebagai sedang berlangsung di database, skrip akan mengunduh halaman dan jika berhasil, tandai url yang diunduh dalam database dan mengirimkan konten ke skrip lain yang menguraikan halaman, tautan baru ditambahkan ke database ketika mereka ditemukan. Keuntungan dari database di sini adalah sentralisasi - banyak skrip dapat meminta database secara bersamaan dan (selama transaksi bersifat atomik) orang dapat yakin bahwa setiap halaman hanya akan diunduh satu kali.

Beberapa poin tambahan menyebutkan - ada batasan (saya percaya 20) pada jumlah instance berdasarkan permintaan yang dapat Anda jalankan pada satu waktu - jika Anda berencana untuk melampaui batas itu, Anda akan perlu meminta AWS untuk meningkatkan akun Anda batas. Akan jauh lebih ekonomis bagi Anda untuk menjalankan instance spot, dan untuk meningkatkan angka Anda ketika harga spot rendah (mungkin satu instance berdasarkan permintaan untuk menjaga semuanya terorganisir, dan sisanya, instance spot).

Jika waktu adalah prioritas lebih tinggi daripada biaya untuk Anda, contoh komputasi cluster menawarkan bandwidth 10Gbps - dan akan menghasilkan bandwidth unduhan terbesar.

Rekap: coba beberapa instance besar (daripada banyak instance kecil) dan jalankan beberapa unduhan bersamaan pada setiap instance - tambahkan lebih banyak instance jika Anda menemukan bandwidth terbatas, pindahkan ke instance lebih besar jika Anda menemukan diri Anda terikat CPU / memori.

cyberx86
sumber
4

Kami mencoba melakukan hal serupa, dan inilah 5 sen saya:

  1. Dapatkan 2-3 server tanpa meteran murah, mis. Tidak membayar bandwidth.

  2. Gunakan python dengan asyncore. Asyncore adalah cara lama untuk melakukan sesuatu, tetapi kami menemukan itu berfungsi lebih cepat daripada metode lainnya. Kelemahannya adalah bahwa pencarian DNS diblokir, yaitu bukan "paralel". Menggunakan asyncore, kami berhasil mengikis URL 1M selama 40 menit, menggunakan inti XEON 4 tunggal, RAM 8 GB. Rata-rata beban di server kurang dari 4 (itu sangat baik untuk 4 core).

  3. Jika Anda tidak suka asyncore, coba gevent. Bahkan melakukan DNS non blocking. Menggunakan gevent, 1M diunduh sekitar 50 menit pada perangkat keras yang sama. Rata-rata beban di server sangat besar.

Catatan kami memang menguji banyak pustaka Python, seperti grequest, curl, liburl / liburl2, tapi kami tidak menguji Twisted .

  1. Kami memang menguji PHP + curl + beberapa proses, itu melakukan pekerjaan selama sekitar satu jam, tetapi rata-rata memuat di server sangat besar.
Nick
sumber
"Tidak terukur" biasanya berarti "kami mematikan Anda saat kami menyukainya", menurut pengalaman saya.
ceejayoz
dalam pengalaman saya, "Tidak Dimeter" berarti dibatasi hingga 100 MBit atau lebih
Nick