【Flask 3.1.2】4 访问 API 并通过队列处理任务

一、测试Redis

我这里没有配置密码等


import redis

REDIS_CONN_PARAMS = {
    "host": '127.0.0.1',
    "password": '',
    "port": 6379,
    "encoding": 'utf-8'
}
conn = redis.Redis(**REDIS_CONN_PARAMS)
conn.lpush("task_1", "123")
conn.lpush("task_1", "456")
conn.lpush("task_1", "789")

data = conn.rpop("task_1")
print(data)

成功获取输出
image

二、请求发送到任务队列

服务端代码

import uuid
from flask import Flask, request, jsonify
import redis
import json

app = Flask(__name__)


@app.route("/task", methods=["POST"])
def task():
    """
    请求的数据格式要求:{"ordered_string": "..."}
    """

    ordered_string = request.json.get("ordered_string")
    if not ordered_string:
        return jsonify({'status': False, 'error': "参数错误"})

    # 生成任务ID
    tid = str(uuid.uuid4())

    # 1. 放入到redis队列中

    task_dict = {
        'tid': tid,
        'data': ordered_string
    }
    REDIS_CONN_PARAMS = {
        "host": '127.0.0.1',
        "password": '',
        "port": 6379,
        "encoding": 'utf-8'
    }
    conn = redis.Redis(**REDIS_CONN_PARAMS)
    conn.lpush("task_1", json.dumps(task_dict))

    # 2. 给用户返回
    return jsonify({
        'status': True,
        'data': tid,
        'message': "正在处理中,预计10分钟完成"
    })


if __name__ == '__main__':
    app.run(host="127.0.0.1", port=5000)

请求端代码

import requests

# 目标URL
url = "http://127.0.0.1:5000/task"

# 要发送的请求体数据(字典形式)
data = {
    "ordered_string": "dnsaonv039h09g095h1nnoc0wjv91ncmosad01-e95ghwe9nfc0mq"
}

# 发送POST请求
response = requests.post(url, json=data)

# 处理响应
print("状态码:", response.status_code)  # 200表示成功
print("响应内容:", response.text)        # 响应的文本内容

# 如果响应是JSON格式,可以直接解析
if response.status_code == 200:
    try:
        json_data = response.json()
        print("JSON响应:", json_data)
    except ValueError:
        print("响应不是JSON格式")

image

三、Worker.py 读取任务队列,写入结果队列

import hashlib
import redis
import json

def get_task():
    REDIS_CONN_PARAMS = {
        "host": '127.0.0.1',
        "password": '',
        "port": 6379,
        "encoding": 'utf-8'
    }
    conn = redis.Redis(**REDIS_CONN_PARAMS)
    data = conn.brpop("task_1", timeout=10) # 阻塞式取任务,最长等待10s

    if not data:
        return

    # data是一个元组(键, 值)
    value = data[1].decode('utf-8') # 解码
    return json.loads(value)

def set_result(tid, value):
    REDIS_CONN_PARAMS = {
        "host": '127.0.0.1',
        "password": '',
        "port": 6379,
        "encoding": 'utf-8'
    }
    conn = redis.Redis(**REDIS_CONN_PARAMS)
    conn.hset("task_1_result", tid, value)

def run():
    while True:
        # 1. 获取Redis中的任务
        task_dict = get_task()
        print(task_dict)
        if not task_dict:
            continue

        # 2. 执行耗时操作 这里假设任务是返回签名
        ordered_string = task_dict['data']
        encrypt_string = ordered_string + "dsj08u3hvhn9219bvnzc0102u8vhkzc"
        obj = hashlib.md5(encrypt_string.encode('utf-8'))
        sign = obj.hexdigest()

        # 3.写入结果队列 (redis的hash)
        tid = task_dict['tid']
        set_result(tid, sign)


if __name__ == '__main__':
    run()

四、请求端读取结果队列

import uuid
from flask import Flask, request, jsonify
import redis
import json

app = Flask(__name__)


@app.route("/task", methods=["POST"])
def task():
    """
    请求的数据格式要求:{"ordered_string": "..."}
    """

    ordered_string = request.json.get("ordered_string")
    if not ordered_string:
        return jsonify({'status': False, 'error': "参数错误"})

    # 生成任务ID
    tid = str(uuid.uuid4())

    # 1. 放入到redis队列中

    task_dict = {
        'tid': tid,
        'data': ordered_string
    }
    REDIS_CONN_PARAMS = {
        "host": '127.0.0.1',
        "password": '',
        "port": 6379,
        "encoding": 'utf-8'
    }
    conn = redis.Redis(**REDIS_CONN_PARAMS)
    conn.lpush("task_1", json.dumps(task_dict))

    # 2. 给用户返回
    return jsonify({
        'status': True,
        'data': tid,
        'message': "正在处理中,预计10分钟完成"
    })

@app.route("/result", methods=["GET"])
def result():
    tid = request.args.get("tid")
    if not tid:
        return jsonify({"status": False, 'error': "参数错误"})

    REDIS_CONN_PARAMS = {
        "host": '127.0.0.1',
        "password": '',
        "port": 6379,
        "encoding": 'utf-8'
    }
    conn = redis.Redis(**REDIS_CONN_PARAMS)
    sign = conn.hget("task_1_result", tid)
    if not sign:
        return jsonify({
            "status": True,
            "data": "",
            "message": "未完成 请继续等待"
        })
    print(sign)
    sign_string = sign.decode('utf-8')
    conn.hdel("task_1_result", tid) # 拿完就删除
    return jsonify({
        "status": True,
        "data": sign_string
    })

if __name__ == '__main__':
    app.run(host="127.0.0.1", port=5000)

五、模拟访问

运行请求端代码,获取结果:

TeamViewer-000004

通过返回的id, 访问:http://127.0.0.1:5000/result?tid=772592f9-13f8-46ca-9cca-c8a7a62bee15

得到结果:
image

六、优化为连接池

服务端

import uuid
from flask import Flask, request, jsonify
import redis
import json

app = Flask(__name__)

REDIS_POOL = redis.ConnectionPool(
    host='127.0.0.1',
    password='',
    port=6379,
    encoding='utf-8',
    max_connections=100
)
TASK_QUEUE = "task_1"
RESULT_QUEUE = "task_1_result"

@app.route("/task", methods=["POST"])
def task():
    """
    请求的数据格式要求:{"ordered_string": "..."}
    """

    ordered_string = request.json.get("ordered_string")
    if not ordered_string:
        return jsonify({'status': False, 'error': "参数错误"})

    # 生成任务ID
    tid = str(uuid.uuid4())

    # 1. 放入到redis队列中

    task_dict = {
        'tid': tid,
        'data': ordered_string
    }

    conn = redis.Redis(connection_pool=REDIS_POOL)
    conn.lpush(TASK_QUEUE, json.dumps(task_dict))

    # 2. 给用户返回
    return jsonify({
        'status': True,
        'data': tid,
        'message': "正在处理中,预计10分钟完成"
    })

@app.route("/result", methods=["GET"])
def result():
    tid = request.args.get("tid")
    if not tid:
        return jsonify({"status": False, 'error': "参数错误"})

    conn = redis.Redis(connection_pool=REDIS_POOL)
    sign = conn.hget(RESULT_QUEUE, tid)
    if not sign:
        return jsonify({
            "status": True,
            "data": "",
            "message": "未完成 请继续等待"
        })
    print(sign)
    sign_string = sign.decode('utf-8')
    conn.hdel(RESULT_QUEUE, tid) # 拿完就删除
    return jsonify({
        "status": True,
        "data": sign_string
    })

if __name__ == '__main__':
    app.run(host="127.0.0.1", port=5000)

Worker.py

import hashlib
import redis
import json

REDIS_POOL = redis.ConnectionPool(
    host='127.0.0.1',
    password='',
    port=6379,
    encoding='utf-8',
    max_connections=100
)
TASK_QUEUE = "task_1"
RESULT_QUEUE = "task_1_result"

def get_task():
    conn = redis.Redis(connection_pool=REDIS_POOL)
    data = conn.brpop(TASK_QUEUE, timeout=10) # 阻塞式取任务,最长等待10s

    if not data:
        return

    # data是一个元组(键, 值)
    value = data[1].decode('utf-8') # 解码
    return json.loads(value)

def set_result(tid, value):
    conn = redis.Redis(connection_pool=REDIS_POOL)
    conn.hset(RESULT_QUEUE, tid, value)

def run():
    while True:
        # 1. 获取Redis中的任务
        task_dict = get_task()
        print(task_dict)
        if not task_dict:
            continue

        # 2. 执行耗时操作 这里假设任务是返回签名
        ordered_string = task_dict['data']
        encrypt_string = ordered_string + "dsj08u3hvhn9219bvnzc0102u8vhkzc"
        obj = hashlib.md5(encrypt_string.encode('utf-8'))
        sign = obj.hexdigest()

        # 3.写入结果队列 (redis的hash)
        tid = task_dict['tid']
        set_result(tid, sign)


if __name__ == '__main__':
    run()

参考资料

[1] 【最快速度搞定Flask-框架教程】11~14

posted @ 2025-08-27 10:48  苦涩如影相随固  阅读(18)  评论(0)    收藏  举报