- 場景:當我們爬蟲或者獲取資料需要很長的時間計算或者等待,這種情況情況下基於API與worker模式完成交付
- 1.API端:用flask框架
import json
import uuid
import redis
from flask import Flask, request, jsonify
app = Flask(__name__)
pool = redis.ConnectionPool(host='127.0.0.1', port=6379, password='123456',encoding='utf-8', max_connections=1000)
@app.route("/task",method=["POST"])
def task():
# 構建引數
total_dict = {}
user_dict = request.json
total_dict.update(user_dict)
total_dict.update({"token":"1231312","sign":"dsfewfwef"})
# 建立任務ID
task_id = str(uuid.uuid4())
# 放入redis
conn = redis.Redis(connection_pool=pool)
task_info = {"uid":task_id,"info":total_dict}
conn.lpush("task_queue",json.dumps(task_info))
return jsonify({"status":True,"data":task_id})
@app.route("/fetch",method=["GET"])
def fetch():
# 透過url傳遞任務id
task_id = request.args.get("task_id")
conn = redis.Redis(connection_pool=pool)
result = conn.hget("task_result",task_id)
if not result:
return jsonify({"status":False,"data":"任務還在執行中"})
conn.hdel("task_result",task_id)
result_string = result.decode('utf-8')
return jsonify({"status":True,"data":result_string})
if __name__ == '__main__':
app.run(host="127.0.0.1", port=9999)
- 2.客戶端
import time
import requests
# 1.傳送請求(建立任務)
res = requests.post(
url="http://127.0.0.1:9999/task",
json={
"aid": 1,
"bfc": True,
"ctime": int(time.time())
}
)
# {"status": True, "data": "fa5d4f0d-9d29-4008-8097-d1a7d5f9c2cd"}
res_dict = res.json()
task_id = res_dict['data']
# 2.查詢結果
while True:
time.sleep(5)
res = requests.get(
url="http://127.0.0.1:9999/fetch",
params={
"task_id": task_id
}
)
# {"status": False, "data": "任務還在執行中"}
# {"status": True, "data": result_string}
res_dict = res.json()
if not res_dict['status']:
print(res_dict['data'])
continue
print("執行完畢", res_dict['data'])
break
- 3.worker
import random
import time
import redis
import json
POOL = redis.ConnectionPool(host='127.0.0.1', port=6379, password='123456', encoding='utf-8', max_connections=1000)
def run():
while True:
conn = redis.Redis(connection_pool=POOL)
res = conn.brpop(["task_queue"], timeout=30) # ("task_queue",b"{}")
print("取任務:", res)
if not res:
continue
task_dict = json.loads(res[-1].decode('utf-8'))
task_id = task_dict['uid']
# 根據任務資訊去執行任務,耗時:5分鐘、1小時
time.sleep(random.randint(5, 10))
# 結算結果放入結果佇列
conn = redis.Redis(connection_pool=POOL)
conn.hset("task_result", task_id, "11121123123123123")
if __name__ == '__main__':
run()
-
4.執行效果
-
5.此場景適用於計算密集型與長時間耗時任務,我們將API部署在遠端伺服器上,使用本地電腦當做worker,可以節約成本