【web服务】耗时任务基于API与worker模式

  • 场景:当我们爬虫或者获取数据需要很长的时间计算或者等待,这种情况情况下基于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, "执行结果")
"""
redis = {
	"task_result":{
		"fa5d4f0d-9d29-4008-8097-d1a7d5f9c2cd":"执行结果",
		"fa5d4f0d-9d29-4008-8097-d1a7d5f9c3cd":"执行结果",
	}
}
"""


if __name__ == '__main__':
    run()
  • 4.运行效果

  • 5.此场景适用于计算密集型与长时间耗时任务,我们将API部署在远程服务器上,使用本地电脑当做worker,可以节约成本

posted @ 2024-10-15 21:29  Tony_xiao  阅读(12)  评论(0编辑  收藏  举报