每秒幾十萬的大規模網絡爬蟲是如何煉成的?

【CSDN 編者按】數據時代,網絡爬蟲似乎是每個程序員的必備技能,在他們的眼中“一切皆可盤”。通常情況下,Python 憑藉優秀的性能優勢更受到程序員的喜愛,不過在本文中,作者介紹了他們公司一個強大的分佈式網絡爬蟲驅動,由Java編寫的系統能夠每秒可以訪問幾十萬個網頁!

每秒幾十萬的大規模網絡爬蟲是如何煉成的?

作者 | Nariman Jelveh@Mixnode Technologies Inc.

譯者 | 彎月

責編 | 郭芮

出品 | CSDN(ID:CSDNnews)

以下為譯文:

我們公司Mixnode的背後由一個極其高效的分佈式網絡爬蟲驅動,每秒可以訪問幾十萬個網頁。雖然在使用Mixnode時,你從來不需要考慮有關網絡抓取的東西,但還是有很多人詢問我們如何才能如此快速地抓取這麼多網頁。

在這篇文章中,我將與大家分享多年來我們在構建與優化爬蟲方面所獲得的經驗以及教訓。

Java

在為項目選擇編程語言時,許多因素都會影響到你的最終決策。內部專業知識、生態系統和原始性能是我們在尋找“完美”的編程語言時必須考慮的主要標準。

最終,我們認為Java是我們的最佳選擇,原因如下:

  • 內部專業知識:因為我們的團隊擁有豐富的Java專業知識,特別是分佈式系統和網絡軟件開發方面的知識,所以我們可以立即開始開發高質量的軟件。
  • 現有的軟件包:大規模的網絡爬蟲需要建立在久經考驗的強大、可擴展且安全的網絡、系統和實用程序模塊之上。Java擁有最活躍的開源生態系統,特別是在網絡和分佈式應用程序方面。Netty、Selenium和Google Guava等軟件包證明Java生態系統擁有高質量的開源模塊。
  • 現有的參考項目:Apache Hadoop、Apache Cassandra和Elasticsearch全都是用Java開發的大型分佈式系統項目的例子,它們為這個生態系統帶來了豐富的專業知識、靈感和先例。當出現問題或有疑問時,通常我們都會發現曾有人經歷過相同或類似的情況。這創建了一個強大的網絡,從而使得用Java開發高性能數據驅動應用程序的過程變得更加簡單且經濟實惠。
  • 原始性能和可靠性:在性能和可靠性方面,Java擁有靜態類型,強大的垃圾收集以及久經實戰考驗的虛擬機等最重要的特性。

雖然我們的核心網絡爬蟲引擎是用Java編寫的,但在為手頭的工作選擇編程語言時我們都很務實。例如,我們也使用其他語言(例如Python,Perl和Node.js)來編寫腳本、配置、監視、報告和管道的其他部分。

無共享架構

在Mixnode,我們的集群採用了無共享架構,工作負載在獨立的無狀態節點上進行分割和分佈,這可以消除大規模分佈式系統的災難——單點故障。另外,該架構允許我們逐個節點更新和升級底層軟件,而不會中斷整個操作。

此外,無共享架構大大減少了節點之間的通信開銷,從而為我們提供了額外的性能提升。

速率限制模塊必須保證安全

網站的主要設計目的是供人類訪問,一位普通用戶每分鐘只能瀏覽很少的頁面。網絡爬蟲每秒能夠訪問數千甚至數百萬個網頁,因此,如果不小心,網絡爬蟲很容易在很短的時間內耗盡網站資源,造成破壞性的後果。而且,一個普通的網站會有多個機器人同時抓取,所以這個問題會被放大。

因此,每個網絡爬蟲也有責任對自己的請求速率進行限制,換句話說,確保連續兩次訪問之間有適當的延遲。你需要對請求速率進行限制的三個最重要的標準是:主機名和IP地址。

很顯然,這項工作需要從一開始就做到盡善盡美。由於一個簡單的錯誤就可能對你正在抓取的網站造成破壞性的後果,所以不容許出錯。在多線程環境中,在跟蹤請求和速率限制參數時,你還應該格外小心以防止競爭。

緩存是王道

在構建大規模數據驅動的應用程序時,緩存網絡事務通常是不可避免的,至少在管道的某些部分如此,特別是當相較於其他任務網絡輸入/輸出更頻繁且開銷更大的情況下。但是,在大規模網絡爬取的情況下,緩存不僅是不可避免的,而且是在編寫代碼之前就需要考慮的事項。

大規模網絡爬取的情況下,有兩個操作需要及時緩存:

  • Robots.txt查找:從某個主機上訪問的每個URL獲取該主機robots.txt文件的全新副本幾乎是不可能的,因此,你需要構建一個分佈式的預讀緩存,能夠持有並定期更新數百萬個網站的robots.txt文件。
  • DNS解析:對於絕大多數URL,你需要至少執行一次DNS解析才能下載,這會增加每秒數千次的查詢。因此,DNS服務器必然會限制你的訪問,或者在過重的負荷下崩潰。無論是哪種情況都會導致爬蟲停止,唯一的解決辦法就是儘可能緩存DNS解析結果,並最大限度地減少不必要的查詢。

解析HTML

爬蟲的基本任務之一就是從它訪問的每個頁面中提取鏈接(即解析),以便將它們添加到需要訪問頁面的隊列中。如果你需要大規模的爬取,那麼最好有一個高性能的HTML解析器,因為你需要提取大量的鏈接和元數據。

大多數HTML解析庫會優先考慮簡單性、易用性和通用性,一般來講這是正確的設計。由於我們需要高速的鏈接提取,所以最終我們決定編寫自己的解析器,並針對查找鏈接和一些原始DOM的查詢功能進行了優化。

HTML解析器還需要具有彈性,經過全面的測試,並且能夠處理大量出現的異常情況,因為並非每個HTML文檔都是有效的。

網絡優化

通常操作系統的默認配置無法處理大規模網絡爬蟲的網絡需求。通常我們需要根據具體情況,優化操作系統的網絡堆棧,使其發揮最大潛力。對於大規模的網絡爬蟲來說,優化的目標在於最大化吞吐量和打開連接的數量。

以下是我們經常會用到的有關該主題的一些有用的資源:

  • Linux網絡性能參數
  • https://github.com/leandromoreira/linux-network-performance-parameters
  • 優化Web服務器,實現高吞吐量和低延遲
  • https://blogs.dropbox.com/tech/2017/09/optimizing-web-servers-for-high-throughput-and-low-latency/
  • Red Hat公司Linux網絡性能調整指南
  • https://access.redhat.com/sites/default/files/attachments/20150325_network_performance_tuning.pdf

小結

構建大規模網絡爬蟲是一項長期的項目,也是一項複雜的工作。我們必須精心設計和測試不同的模塊,同時還需仔細觀測和研究權衡利弊。許多我們日常使用的計算機軟件組件都無法在網絡爬蟲的工作負載下正常運行,因此我們需要從頭開始設計,同時還需不斷審查和優化其他組件,才能適應不斷變化的不斷擴大的網絡。

我們的網絡級爬蟲經過了漫長的發展,才成為了成熟穩定的平臺,我們期待分享更多關於學習構建基礎架構的經驗教訓。

原文:https://www.mixnode.com/blog/posts/lessons-learned-building-a-modern-massive-scale-web-crawler

本文為 CSDN 翻譯,如需轉載,請註明來源出處。

相關推薦

推薦中...