- Berbagi pengalaman nyata merayapi 1 miliar halaman web dalam 24 jam serta proses merancang sistem crawling web modern
- Dengan hardware dan infrastruktur cloud terbaru, crawling skala besar berhasil diwujudkan dengan biaya di kisaran beberapa ratus dolar, dan ditemukan bahwa bottleneck utamanya adalah parsing
- Meski hanya melakukan parsing HTML tanpa menjalankan JavaScript, ternyata masih banyak halaman web yang tetap dapat diakses
- Merancang arsitektur cluster node berbasis Redis, memaksimalkan efisiensi lewat sharding per domain dan optimasi struktur proses
- Alih-alih jaringan, bottleneck utama justru ada pada CPU, SSL, dan memori, sementara pengelolaan frontier domain besar menjadi isu kunci
Definisi masalah
- Menetapkan target merayapi 1 miliar halaman web dalam 24 jam
- Anggaran ditetapkan hanya beberapa ratus dolar (akhirnya sekitar 462 dolar), disesuaikan dengan level serupa seperti kasus tahun 2012
- Hanya mengumpulkan HTML, tanpa menjalankan JavaScript, dan mengekstrak hanya tautan
<a>
- Menekankan politeness (crawling yang sopan): mematuhi robots.txt, menyertakan informasi User Agent, mengecualikan domain jika diminta, hanya menargetkan 1 juta domain terpopuler, serta memberi jeda 70 detik untuk domain yang sama
- Menjamin toleransi kesalahan: saat node gagal, sistem dirancang untuk restart sambil menerima kemungkinan sebagian data hilang, dengan pendekatan berbasis sampel
Arsitektur dan desain
- Berbeda dari gaya wawancara desain sistem konvensional (terdistribusi per fungsi), dipilih struktur di mana setiap node menangani sendiri seluruh fungsi seperti status crawl, parsing, fetching, penyimpanan, dan lainnya
- Menggunakan 12 node, dan tiap node memakai instance
i7i.4xlarge (16 vCPU, 128GB RAM, 10Gbps, penyimpanan 3750GB)
- Setiap node terdiri dari 1 Redis, 9 fetcher, dan 6 proses parser
- Redis menyimpan frontier per domain, fetch queue, URL yang sudah dikunjungi, Bloom filter, robots.txt, parsing queue, dan lainnya
- Fetcher: mengambil URL dari queue per domain lalu melakukan fetch, menjalankan 6000~7000 tugas bersamaan dengan asyncio, dengan bottleneck utama di CPU
- Parser: 80 worker async, menangani parsing HTML dan ekstraksi tautan, pekerjaan yang berpusat pada CPU
- Penyimpanan: memilih storage lokal instance alih-alih S3, untuk menekan biaya penyimpanan halaman berukuran besar
- Sharding: domain didistribusikan per node tanpa komunikasi silang, dan jumlah node sharding disesuaikan untuk mengatasi ketimpangan domain populer
Alternatif utama dan eksperimen
- Mencoba berbagai penyimpanan seperti SQLite dan PostgreSQL, namun pada akhirnya Redis memberikan performa terbaik
- Pernah mencoba penskalaan vertikal (satu instance besar), tetapi muncul bottleneck akibat keterbatasan software, sehingga akhirnya dipilih struktur penskalaan horizontal (banyak node)
- Menghilangkan komunikasi silang antarnode, dan memusatkan pemrosesan paralel di dalam masing-masing node
Pelajaran utama selama proses crawling
Parsing adalah bottleneck terbesar
- Ukuran halaman rata-rata kini jauh lebih besar dibanding masa lalu (2012: 51KB), yakni rata-rata 242KB dan median 138KB
- Mengganti lxml dengan selectolax (berbasis Lexbor) secara signifikan meningkatkan kecepatan parsing
- Efisiensi ditingkatkan dengan memotong ukuran maksimum halaman menjadi 250KB
- Hasilnya, satu parser mampu mem-parsing 160 halaman per detik, dan pada akhirnya rasio fetcher:parser disetel ke 9:6 untuk menangani sekitar 950 halaman/detik
Fetching: hal yang menjadi lebih mudah dan lebih sulit
- Bandwidth jaringan justru bukan bottleneck (dari 25Gbps per node, hanya sekitar 8Gbps yang digunakan)
- Bottleneck DNS juga tidak menjadi masalah karena target hanya domain populer
- Sebaliknya, SSL handshake muncul sebagai salah satu bottleneck terbesar, memakan 25% dari total penggunaan CPU
- Karena sebagian besar halaman kini sudah berpindah ke HTTPS, biaya CPU ikut meningkat
Eksekusi crawling nyata dan masalah yang muncul
- Eksperimen awal hanya berjalan beberapa jam dengan satu node (
i7i.2xlarge), lalu crawl utama diperluas menjadi 12 node
- Muncul masalah memori: frontier domain populer (URL yang belum dikunjungi) membengkak hingga puluhan GB, menyebabkan node berulang kali down
- Domain populer (misalnya yahoo.com, wikipedia.org) atau situs dengan jumlah tautan yang sangat besar memicu masalah ini
- Domain bermasalah dikecualikan secara manual, dan saat gangguan terjadi, pemulihan dilakukan dengan me-restart node serta memotong frontier
Perbandingan teori dan praktik
- Dibandingkan dengan perkiraan metode textbook sebelumnya, yaitu "10 miliar halaman dalam 5 hari dengan 5 mesin", angka di dunia nyata ternyata cukup mendekati
- Jika melihat utilisasi jaringan dan CPU nyata tiap node, throughput yang lebih tinggi masih mungkin dicapai tergantung sejauh mana optimasi dilakukan
Tugas lanjutan dan pemikiran ke depan
- Menegaskan kembali bahwa cukup banyak halaman web masih bisa diakses hanya dengan parsing HTML, tetapi platform besar (misalnya GitHub) sering menyimpan konten bermakna di dalam JS sehingga tidak bisa diparse
- Sebagai tugas masa depan, perlu dieksplorasi biaya dan metode crawling skala besar berbasis rendering JS
- Analisis data (metadata halaman yang benar-benar terkumpul, rasio aktif/tidak aktif, dan sebagainya) juga disebut sebagai topik lanjutan
- Belakangan ini, crawling agresif yang digabungkan dengan AI semakin meningkat, dan lingkungan web crawling kembali berubah seiring munculnya sistem pertahanan baru seperti pay-per-crawl dari Cloudflare
3 komentar
Luar biasa..tepuk tangan...
Menarik. Saya membacanya dengan baik, terima kasih.
Luar biasa.. ini pertarungan antara tombak dan perisai ya, haha