Crawlab的核心原理是什么
這篇文章將為大家詳細講解有關Crawlab的核心原理是什么,文章內容質量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關知識有一定的了解。
為什么需要爬蟲管理平臺
對于一般的爬蟲愛好者來說,寫一個單機爬蟲腳本已經足夠,而且Scrapy這樣的優秀爬蟲框架能夠讓開發者輕松調試、編寫一個簡單的爬蟲,需要定時任務就直接上Crontab,分分鐘搞定。然而,一般的企業對爬蟲的要求相對較高,其中主要涉及一個問題,也就是規模(Scale)。當然,這里的規模是指大型規模。爬蟲的規模分為兩種:一種是爬蟲需要抓取大量的數據(Volume),例如全網抓取淘寶的商品;另一種是爬蟲需要涵蓋大量的網站(Coverage),例如搜索引擎。
不同的規模需要有不同的架構策略(如下圖):
-
當網站數量只有一個,抓取結果不多時,只需要單機即可,并不需要分布式爬蟲;
-
但當需要抓取結果量級提升時,例如全網抓取淘寶,就需要用分布式爬蟲了,這是因為單個機器的帶寬和計算資源不足以做到全網抓取,而且為了應對反爬蟲技術,還需要大量的代理IP;
-
同理,當需要抓取網站的數量增多時,例如你需要創建一個新聞搜索引擎,你同樣需要多臺機器來獲取足夠的帶寬和計算資源;
-
對于同時要求Volume和Coverage的應用,不是一般的小企業或個人能做的,對不管是人力和機器的資源都非常高。
而爬蟲管理平臺就是針對情況(2)、(3)、(4)而存在的分布式管理平臺,能夠讓用戶輕松管理多個爬蟲或多機運行的爬蟲。
Crawlab從誕生之初就解決了分布式爬蟲問題,最早采用了Celery作為分布式任務調度引擎,以Redis作為消息隊列,HTTP請求作為節點通信媒介,簡單地實現了分布式管理。但隨著用戶不斷使用Crawlab,發現這樣的方式并不是很方便,用戶需要指定節點的IP地址和API端口,而且還不能指定節點執行任務。因為各種問題,在最新版本v0.3.0用Golang重構后端的時候,就將Celery棄用了,轉而自己開發分布式節點的監控和通信應用,這樣更加靈活和高效。本文是核心原理介紹,下面將著重介紹Crawlab的分布式架構原理(Golang版本)。
整體架構
Crawlab的整體架構如下圖,由五大部分組成:
-
主節點(Master Node):負責任務派發、API、部署爬蟲等;
-
工作節點(Worker Node):負責執行爬蟲任務;
-
MongoDB數據庫:存儲節點、爬蟲、任務等日常運行數據;
-
Redis數據庫:儲存任務消息隊列、節點心跳等信息。
-
前端客戶端:Vue應用,負責前端交互和向后端請求數據。
以執行爬蟲任務為例,它是Crawlab中常見的使用場景,我們來看看它具體是如何工作的:
-
前端向主節點發起請求,要求指定在某一工作節點執行任務;
-
主節點收到該請求,并將任務數據推送到Redis任務隊列中;
-
工作節點持續監聽Redis任務隊列,并利用LPOP獲取任務;
-
工作節點執行任務,并將結果寫回到儲存數據庫;
以上就是執行爬蟲任務的大致流程。當然,這還不是全部,我們還需要考慮日志處理、并發執行、取消任務等細節問題。具體的處理信息,請查看相關文檔和源代碼。
總的來說,可以將主節點看作是Crawlab整體架構的中控系統,理解為Crawlab的大腦;工作節點是實際干活的部分,是Crawlab的運動軀體;MongoDB和Redis是負責通信交流的,可以看作Crawlab的血液和神經網絡。這些模塊一起構成了一個完整、自洽、相互協作的系統。
節點注冊和監控
節點監控主要是通過Redis來完成的(如下圖)。
工作節點會不斷更新心跳信息在Redis上,利用HSET nodes <node_id> <msg>,心跳信息<msg>包含節點MAC地址,IP地址,當前時間戳。
主節點會周期性獲取Redis上的工作節點心跳信息。如果有工作節點的時間戳在60秒之前,則考慮該節點為離線狀態,會在Redis中刪除該節點的信息,并在MongoDB中設置為"離線";如果時間戳在過去60秒之內,則保留該節點信息,在MongoDB中設置為"在線"。
該架構的優點
這樣,就做到了一個監控節點是否在線的節點注冊系統。這樣架構的好處在于,節點之間根本不用像HTTP、RPC那樣IP或端口,只需要知道Redis的地址就可以完成節點注冊和監控。因此,也就減少了用戶配置節點的操作,簡化了使用流程。同時,由于隱藏了IP地址和端口,也更為安全。另外,相較于Celery版本的監控,我們去除了Flower服務,不用在服務中單獨起一個Flower服務的進程,減少了開銷。
下圖是Crawlab UI界面上的節點之間的關系圖(拓撲圖)。
該架構的缺點
相較于一些常見的分布式架構,例如Zookeeper,Crawlab還存在一些不完善的地方。
高可用性(High Availability)是Crawlab暫時還沒有做得很好的。例如,當主節點宕機的時候,整個系統就會癱瘓,因為主節點是Crawlab的大腦中樞,負責很多功能。如果主節點宕機,前端就無法獲取API數據,任務無法調度,當然也無法監控節點了。雖然Zookeeper沒有將可用性(Availability)做得非常完善,但其投票選舉機制保證了其一定程度的高可用。如果Crawlab要改善這一點的話,會在主節點宕機后,用一定的方式選舉出另一個主節點,保證高可用。
節點通信
如果仔細看上面的整體架構圖的話,你可能會注意到Crawlab中通信有兩種。一種是同步信息(Sync via Msg),另一種是派發任務(Assign Tasks)。這兩種通信分別叫即時通信和延遲通信。下面分別介紹。
即時通信
即時通信是指某節點A通過某種媒介向另一節點B發送信息,取決于是否為雙向通信,節點B收到信息后可能會通過同一種媒介將信息回復給節點A。
Crawlab的即時通信是通過Redis的PubSub來實現的(如下圖)。
所謂PubSub,簡單來說是一個發布訂閱模式。訂閱者(Subscriber)會在Redis上訂閱(Subscribe)一個通道,其他任何一個節點都可以作為發布者(Publisher)在該通道上發布(Publish)消息。
在Crawlab中,主節點會訂閱nodes:master通道,其他節點如果需要向主節點發送消息,只需要向nodes:master發布消息就可以了。同理,各工作節點會各自訂閱一個屬于自己的通道nodes:<node_id>(node_id是MongoDB里的節點ID,是MongoDB ObjectId),如果需要給工作節點發送消息,只需要發布消息到該通道就可以了。
一個網絡請求的簡單過程如下:
-
客戶端(前端應用)發送請求給主節點(API);
-
主節點通過Redis PubSub的
<nodes:<node_id>通道發布消息給相應的工作節點; -
工作節點收到消息之后,執行一些操作,并將相應的消息通過
<nodes:master>通道發布給主節點; -
主節點收到消息之后,將消息返回給客戶端。
Crawlab的獲取日志、獲取系統信息、取消任務、告知節點獲取爬蟲文件都是通過即時通信完成的。
而實現代碼相對來說有些復雜。下面是主節點的PubSub回調函數。
funcMasterNodeCallback(channelstring,msgStrstring){
//反序列化
varmsgNodeMessage
iferr:=json.Unmarshal([]byte(msgStr),&msg);err!=nil{
log.Errorf(err.Error())
debug.PrintStack()
return
}
ifmsg.Type==constants.MsgTypeGetLog{
//獲取日志
fmt.Println(msg)
time.Sleep(10*time.Millisecond)
ch:=TaskLogChanMap.ChanBlocked(msg.TaskId)
ch<-msg.Log
}elseifmsg.Type==constants.MsgTypeGetSystemInfo{
//獲取系統信息
fmt.Println(msg)
time.Sleep(10*time.Millisecond)
ch:=SystemInfoChanMap.ChanBlocked(msg.NodeId)
sysInfoBytes,_:=json.Marshal(&msg.SysInfo)
ch<-string(sysInfoBytes)
}
}
這里其實是用msg.Type來區分消息類別,如果要擴展的話需要寫不少if/else。工作節點的回調函數也需要寫類似的邏輯。
這個可能跟HTTP請求和RPC通信相較來說麻煩一些。不過,這其實和WebSocket非常像(對WebSocket不了解的同學可以看看韋世東最近的文章《開發者必知必會的 WebSocket 協議》),都需要在客戶端和服務端定義回調函數。一個改進方法是不用if/else來區分信息類別,轉而用PubSub頻道名稱,監聽多個頻道??傊?,具體實踐中怎么選擇,還需要考慮實際情況。
延遲通信
延遲通信對即時性要求不高,不需要節點或客戶端對請求即時回復。通常來說,延遲通信的實現方式有隊列、輪詢等方式。這樣的方式不要求即時性。延遲通信主要是用作需要長時間的操作,例如發送郵件、數據處理、構建應用等等。
Crawlab中的延遲通信主要包含任務隊列以及輪詢,都是通過Redis來實現的。任務隊列是用作爬蟲任務執行:主節點接收抓取請求后,將執行任務的消息推到任務隊列中,工作節點不斷輪詢任務隊列,獲取任務并執行(如下圖)。Crawlab爬蟲任務執行的詳情請參見相關文檔和源代碼。
Crawlab的延遲通信主要包括爬蟲任務執行和爬蟲部署。爬蟲任務執行這里不再贅述。下面簡單介紹一下爬蟲部署(流程如下圖)。
整個爬蟲部署的生命周期:
-
主節點每5秒,會從爬蟲的目錄獲取爬蟲信息,然后更新到數據庫(這個過程不涉及文件上傳);
-
主節點每60秒,從數據庫獲取所有的爬蟲信息,然后將爬蟲打包成zip文件,并上傳到MongoDB GridFS,并且在MongoDB的spiders表里寫入file_id文件ID;
-
主節點通過Redis PubSub發布消息(file.upload事件,包含文件ID)給工作節點,通知工作節點獲取爬蟲文件;
-
工作節點接收到獲取爬蟲文件的消息,從MongoDB GridFS獲取zip文件,并解壓儲存在本地。
這樣,所有爬蟲將被周期性的部署在工作節點上。
在后續的開發中,Crawlab將會加入郵件通知、短信通知、微信推送等功能。而這些都是屬于延遲通信的范疇,主要實現方法無外乎隊列和輪詢。
分布式實踐 - 抓取上百個新聞網站
下面將介紹一個多機爬蟲的實際應用場景,幫助大家深入理解Crawlab的分布式原理。
首先,你可能需要足夠的網絡帶寬,因為需要抓取的網站上百了,不是簡簡單單的單機爬蟲,你需要多臺機器。這里只是簡單介紹下拓撲架構,并不會詳細介紹大規模爬蟲的去重、反爬、容錯等邏輯。如下圖,每一個工作節點可以限制抓取一部分網站,總共M個網站平均分配給N個工作節點。在Crawlab中就是用指定節點的方式了,這個不難。另外,你也可以通過隨機分配的方式來派發任務,每一個工作節點統計上也會均勻分配到任務,這其實也就是一個負載均衡(Load Balancing)的過程。
總結
以上是生活随笔為你收集整理的Crawlab的核心原理是什么的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Win10安装软件用户账户控制提示管理员
- 下一篇: flash制作车轮往前滚动的动画效果(w