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