爬蟲那些事兒-任務調度系統設計

前言

       對於一家資訊媒體公司而言,爬蟲可以說是第一道,也是最重要的補給線與產品線。爬蟲聚焦於開發與維護各類網絡信息抓取工具,通過獲取到數量大、質量高的數據,爲運營、算法、大數據等各個部門提供數據支持,保證公司的業務良好運行,而調度則是許多抓取程序中比較重要的一環。

一 、任務調度系統設計的重要性

    分佈式系統中比如Hadoop、MapReduce編程模型、還有其它大數據系統都會設計到任務調度。搜索引擎爬蟲、新聞聚合公司爬蟲面對的抓取url種子都是幾十萬、上百萬甚至更多,這麼多網頁種子需要去抓取資源如果沒有一個較好的調度系統,整個系統將會一片混亂。調度系統可以解決以下問題:


試想想如果一會一大堆種子要抓取,一會很長時間沒有任務這就導致,閒的時候機器是空閒的,忙的時候特別忙網絡請求非常頻繁。

好的任務調度,能夠更有效的利用機器資源,達到負載均衡 ,同時提高抓取效率,也能保證數據的平均。

二、設計思路


             圖2-1


  圖2-2


  圖2-3

此調度系統是慢慢迭代開發,如圖2-1,之前的話種子不是特別多,就通過linux crontab 指令0 */5 * * * sh /data/get_xpath/start.sh 去執行,這樣的話無法做到去區分種子,隨着種子數據變多,這種機制完全不符合需求了。後來就採取區別對待如圖2-2,就是多個 crontab 多個程序分別調度不同週期的程序。這樣的解決方法也真是easy啊,當然還可以用另外一種方式進行處理,利用併發包中的Executors.newScheduledThreadPool(1);方式,執行多個scheduleWithFixedDelay方法去實現:代碼如下,

private  ScheduledExecutorService scheduExec = Executors.newScheduledThreadPool(1);
MyTask fifteenMinuTask = new MyTask(60*15);
scheduExec.scheduleWithFixedDelay(fifteenMinuTask, 0, 15, TimeUnit.MINUTES);
MyTask oneHourTask = new MyTask(60*60);
scheduExec.scheduleWithFixedDelay(oneHourTask, 0 , 1, TimeUnit.HOURS);
MyTask fourHourTask = new MyTask(60*60*4);
scheduExec.scheduleWithFixedDelay(fourHourTask, 0, 4, TimeUnit.HOURS);
MyTask twelveHourTask = new MyTask(60*60*12);
scheduExec.scheduleWithFixedDelay(twelveHourTask, 0, 12, TimeUnit.HOURS);

定義了四個任務調度方法,分別15分鐘,1小時,4小時和12小時調度一次~  


圖2-3是最終的調度實現方式,上面的方法不能滿足需求,一個是經常性的對數據庫進行操作,操作效率不高,另外一個就是想修改調度頻率還是需要重新修改代碼,也不能達到數據的平均化。最終形成圖2-3的模式,引入緩存redis,通過定義一個list隊列和hash存儲結構來滿足需要,可以把起想象成多個環。按抓取週期分佈在這個週期的環裏,如



假設一組任務調度週期是10分鐘,讓這組數據平均分配到這600秒這個圓環上,然後不斷的輪詢這個圓 ,正常情況下就能保證相同週期的抓取任務能夠平均的推送到抓取系統中。

數據結構實現是不斷循環list,pop一條然後放到列尾,然後去hash去判斷是否應該推送:now() -last_push_time > = crawler_internal 噹噹前時間減去上一次推送時間就推送到抓取隊列中。


另外說明:當程序運行久了之後,調度可能不那麼均衡,就有隔一段時間進行初始化的操作,刪除redis 相關數據,重新加載最新數據。另外還有就是對數據進行更新,因爲數據庫中的種子表是不斷新增以及更新,同時也會涉及到種子下架和調度週期調整。這些都需要考慮的。

以上就是爬蟲中調度系統的實現方案,通過這種土辦法最終達到需求。~ 






發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章