當前位置:編程學習大全網 - 編程語言 - 如何用 Python 構建壹個簡單的分布式系統

如何用 Python 構建壹個簡單的分布式系統

分布式爬蟲概覽

何謂分布式爬蟲?

通俗的講,分布式爬蟲就是多臺機器多個

spider

對多個

url

的同時處理問題,分布式的方式可以極大提高程序的抓取效率。

構建分布式爬蟲通暢需要考慮的問題

(1)如何能保證多臺機器同時抓取同壹個URL?

(2)如果某個節點掛掉,會不會影響其它節點,任務如何繼續?

(3)既然是分布式,如何保證架構的可伸縮性和可擴展性?不同優先級的抓取任務如何進行資源分配和調度?

基於上述問題,我選擇使用celery作為分布式任務調度工具,是分布式爬蟲中任務和資源調度的核心模塊。它會把所有任務都通過消息隊列發送給各個分布式節點進行執行,所以可以很好的保證url不會被重復抓取;它在檢測到worker掛掉的情況下,會嘗試向其他的worker重新發送這個任務信息,這樣第二個問題也可以得到解決;celery自帶任務路由,我們可以根據實際情況在不同的節點上運行不同的抓取任務(在實戰篇我會講到)。本文主要就是帶大家了解壹下celery的方方面面(有celery相關經驗的同學和大牛可以直接跳過了)

Celery知識儲備

celery基礎講解

按celery官網的介紹來說

Celery

是壹個簡單、靈活且可靠的,處理大量消息的分布式系統,並且提供維護這樣壹個系統的必需工具。它是壹個專註於實時處理的任務隊列,同時也支持任務調度。

下面幾個關於celery的核心知識點

broker:翻譯過來叫做中間人。它是壹個消息傳輸的中間件,可以理解為壹個郵箱。每當應用程序調用celery的異步任務的時候,會向broker傳遞消息,而後celery的worker將會取到消息,執行相應程序。這其實就是消費者和生產者之間的橋梁。

backend:

通常程序發送的消息,發完就完了,可能都不知道對方時候接受了。為此,celery實現了壹個backend,用於存儲這些消息以及celery執行的壹些消息和結果。

worker:

Celery類的實例,作用就是執行各種任務。註意在celery3.1.25後windows是不支持celery

worker的!

producer:

發送任務,將其傳遞給broker

beat:

celery實現的定時任務。可以將其理解為壹個producer,因為它也是通過網絡調用定時將任務發送給worker執行。註意在windows上celery是不支持定時任務的!

下面是關於celery的架構示意圖,結合上面文字的話應該會更好理解

由於celery只是任務隊列,而不是真正意義上的消息隊列,它自身不具有存儲數據的功能,所以broker和backend需要通過第三方工具來存儲信息,celery官方推薦的是

RabbitMQ和Redis,另外mongodb等也可以作為broker或者backend,可能不會很穩定,我們這裏選擇Redis作為broker兼backend。

實際例子

先安裝celery

pip

install

celery

我們以官網給出的例子來做說明,並對其進行擴展。首先在項目根目錄下,這裏我新建壹個項目叫做celerystudy,然後切換到該項目目錄下,新建文件tasks.py,然後在其中輸入下面代碼

這裏我詳細講壹下代碼:我們先通過app=Celery()來實例化壹個celery對象,在這個過程中,我們指定了它的broker,是redis的db

2,也指定了它的backend,是redis的db3,

broker和backend的連接形式大概是這樣

redis://:password@hostname:port/db_number

然後定義了壹個add函數,重點是@app.task,它的作用在我看來就是將add()

註冊為壹個類似服務的東西,本來只能通過本地調用的函數被它裝飾後,就可以通過網絡來調用。這個tasks.py中的app就是壹個worker。它可以有很多任務,比如這裏的任務函數add。我們再通過在命令行切換到項目根目錄,執行

celery

-A

tasks

worker

-l

info

啟動成功後就是下圖所示的樣子

這裏我說壹下各個參數的意思,-A指定的是app(即Celery實例)所在的文件模塊,我們的app是放在tasks.py中,所以這裏是

tasks;worker表示當前以worker的方式運行,難道還有別的方式?對的,比如運行定時任務就不用指定worker這個關鍵字;

-l

info表示該worker節點的日誌等級是info,更多關於啟動worker的參數(比如-c、-Q等常用的)請使用

celery

worker

--help

進行查看

將worker啟動起來後,我們就可以通過網絡來調用add函數了。我們在後面的分布式爬蟲構建中也是采用這種方式分發和消費url的。在命令行先切換到項目根目錄,然後打開python交互端

from

tasks

import

addrs

=

add.delay(2,

2)

這裏的add.delay就是通過網絡調用將任務發送給add所在的worker執行,這個時候我們可以在worker的界面看到接收的任務和計算的結果。

這裏是異步調用,如果我們需要返回的結果,那麽要等rs的ready狀態true才行。這裏add看不出效果,不過試想壹下,如果我們是調用的比較占時間的io任務,那麽異步任務就比較有價值了

上面講的是從Python交互終端中調用add函數,如果我們要從另外壹個py文件調用呢?除了通過import然後add.delay()這種方式,我們還可以通過send_task()這種方式,我們在項目根目錄另外新建壹個py文件叫做

excute_tasks.py,在其中寫下如下的代碼

from

tasks

import

addif

__name__

==

'__main__':

add.delay(5,

10)

這時候可以在celery的worker界面看到執行的結果

此外,我們還可以通過send_task()來調用,將excute_tasks.py改成這樣

這種方式也是可以的。send_task()還可能接收到為註冊(即通過@app.task裝飾)的任務,這個時候worker會忽略這個消息

定時任務

上面部分講了怎麽啟動worker和調用worker的相關函數,這裏再講壹下celery的定時任務。

爬蟲由於其特殊性,可能需要定時做增量抓取,也可能需要定時做模擬登陸,以防止cookie過期,而celery恰恰就實現了定時任務的功能。在上述基礎上,我們將tasks.py文件改成如下內容

然後先通過ctrl+c停掉前壹個worker,因為我們代碼改了,需要重啟worker才會生效。我們再次以celery

-A

tasks

worker

-l

info這個命令開啟worker。

這個時候我們只是開啟了worker,如果要讓worker執行任務,那麽還需要通過beat給它定時發送,我們再開壹個命令行,切換到項目根目錄,通過

這樣就表示定時任務已經開始運行了。

眼尖的同學可能看到我這裏celery的版本是3.1.25,這是因為celery支持的windows最高版本是3.1.25。由於我的分布式微博爬蟲的worker也同時部署在了windows上,所以我選擇了使用

3.1.25。如果全是linux系統,建議使用celery4。

此外,還有壹點需要註意,在celery4後,定時任務(通過schedule調度的會這樣,通過crontab調度的會馬上執行)會在當前時間再過定時間隔執行第壹次任務,比如我這裏設置的是60秒的間隔,那麽第壹次執行add會在我們通過celery

beat

-A

tasks

-l

info啟動定時任務後60秒才執行;celery3.1.25則會馬上執行該任務

  • 上一篇:為什麽程序只能用英語寫,什麽時候能開發出能用漢語寫的程序開發軟件
  • 下一篇:大專,本科,研究生,博士生,博士後..學歷?
  • copyright 2024編程學習大全網