1. 程式人生 > >基於Celery在多臺雲伺服器上實現分散式

基於Celery在多臺雲伺服器上實現分散式

# 起源 最近參加公司裡的一個比賽,比賽內容裡有一項是儘量使用分散式實現專案。因為專案最終會跑在jetsonnano,一個賊卡的開發板,效能及其垃圾。而且要求使用python? 找了很多部落格,講的真的是模稜兩可,最後結合官方文件終於啃出來,寫出來分享一下。 目前本部落格的幾個要點: 1. 使用celery實現分散式 2. 結合flask框架使用 3. 使用Redis作為broker 4. 使用Redis作為backend # 準備工作 ## 安裝環境 需要安裝的環境包括Redis、Celery、Pyhton3.6.9「開發板自帶」 > 這裡需要填坑的是Redis的設定。因為在騰訊雲伺服器、華為雲伺服器、滴滴雲伺服器上做的測試「窮,每個平臺褥點羊毛」,一開始不知道在安全組裡面開放埠,一直連線不上伺服器,很坑。這裡如果沒有使用雲伺服器的話可以跳過安全組這一步的設定,使用了雲伺服器的話,一件開放一下埠,自行百度開放方法。 首先是Redis的設定,Redis需要把預設的120.0.0.1 IP地址修改為0.0.0.0,並把守護程序關閉。 ``` vim redis.conf bind = 0.0.0.0 protected -mode no //從yes改為no ``` ## 安裝celery ``` pip3 install celery -i https://pypi.tuna.tsinghua.edu.cn/simple ``` # 一個簡單的分散式Demo 網上關於建立Celery檔案的描述都很模糊,這裡我的理解是這樣,首先看一下官方給出的Demo: ```Python from celery import Celery app = Celery('tasks', broker='pyamqp://guest@localhost//') @app.task def add(x, y): return x + y ``` 將這個檔案命名為tasks.py 這段程式碼最關鍵的核心是`` app = Celery('tasks', broker='pyamqp://guest@localhost//') `` 既然是分散式,肯定要有worker,幹活的人,也就是雲伺服器,在雲伺服器上需要做的事情是:`` celery -A tasks worker --loglevel=info `` 其中的`` celery -A *** worker --loglevel=info `` *** 就是worker要拿到任務的任務板標誌,只有有個這個標誌,worker才知道到底誰在發任務。 `` broker='pyamqp://guest@localhost//' `` 因為我使用redis來作為任務的存放容器,所以改為 `` broker='redis://guest@localhost//' `` broker是存放任務的地方,所以我把發放任務的伺服器的地址填進去:`` app = Celery('tasks', broker='redis://121.***.***.190:6379') `` 6379為預設的埠號,其實broker這段url應該包括redis的使用者名稱、使用者密碼+IP地址。因為我們前面修改的redis的配置檔案,所以這裡可以無密碼訪問。 ```Python @app.task def add(x, y): return x + y ``` 這一段就是伺服器要傳送出去的任務了。當然伺服器裡不需要包含執行任務所需要的庫,庫安裝在worker的伺服器裡就可以了。「當然add(x,y)啥庫也不需要」。 現在可以來見識一下celery的威力了,把上面修改後的tasks.py放到worker伺服器上面,執行命令:`` celery -A tasks worker --loglevel=info `` 你會看到下面這行: ``` (base) zhaosi@zhaosideMBP *** % celery -A tasks worker --loglevel=info -------------- celery@zhaosideMBP v4.4.7 (cliffs) --- ***** ----- -- ******* ---- macOS-10.15.6-x86_64-64bit 2020-09-05 14:35:13 - *** --- * --- - ** ---------- [config] - ** ---------- .> app: tasks:0x7fd0bb1b16a0 - ** ---------- .> transport: redis://121.***.***.190:6379/8 - ** ---------- .> results: redis://121.***.***.190:6379/7 - *** --- * --- .> concurrency: 8 (prefork) -- ******* ---- .> task events: OFF (enable -E to monitor tasks in this worker) --- ***** ----- -------------- [queues] .> celery exchange=celery(direct) key=celery [tasks] . tasks.add [2020-09-05 14:35:15,566: INFO/MainProcess] Connected to redis://121.***.***.190:6379/8 [2020-09-05 14:35:15,773: INFO/MainProcess] mingle: searching for neighbors [2020-09-05 14:35:17,484: INFO/MainProcess] mingle: all alone [2020-09-05 14:35:18,789: INFO/MainProcess] celery@zhaosideMBP ready. ``` 當你看到最後四行時,YES,最簡單的Demo被你跑起來了 ``` [tasks] . tasks.add ``` 這裡展示的是worker可以接到的任務,當然現在伺服器還沒有釋出任務,worker在持續監聽伺服器上儲存釋出任務的redis資料庫,等著接活。 # 驗收成果 開啟雲伺服器,準備釋出任務「請在伺服器上也建立一個tasks.py,不需要安裝任何依賴」 ``` root@-x:~/pro# python3 Python 3.6.9 (default, Jul 17 2020, 12:50:27) [GCC 8.4.0] on linux Type "help", "copyright", "credits" or "license" for more information. >>> from tasks import add >>> add.delay(1,1) >>> ``` 回到worker伺服器,可以看到任務被接收並且完成了! ``` [2020-09-05 14:41:10,138: INFO/MainProcess] Received task: tasks.add[71c49a0e-2d52-444e-b158-1ae9f1486767] [2020-09-05 14:41:10,223: WARNING/ForkPoolWorker-8] 2 ``` 可以通過result來接受結果: ``` >>> result = add.delay(1,1) >>> result.get() 2 ``` 更復雜的返回值請各位自行探索啦 所謂萬事開頭難,有了這個Demo的幫助,後續的任務會簡單很多。 # 後續 還是官方文件好啊。現在大多數部落格寫的是