在Heroku基于Python Flask开发API时如何等待Worker处理完成后返回响应
核心实现逻辑
你当前的实现是将任务投递到RQ队列后立刻返回任务ID,属于异步即发即走模式,要实现等Worker执行完成后再向客户端返回结果,只需要在路由逻辑中增加任务状态轮询等待流程,拿到Worker的执行结果后再组装JSON响应即可,整个过程不需要修改Worker端的业务代码。
代码修改方案
在你原有POST路由的基础上,增加状态轮询的等待逻辑,适配Heroku平台的请求超时规则,修改后的完整代码如下:
from flask import jsonify import time # 你原有初始化队列、定义login_to_website函数的逻辑保持不变 @app.route('/', methods=['POST']) def automate(): orderNumbers.clear() email = request.args.get('email', None) password = request.args.get('password', None) orderNumber = request.args.get('orderNumber', None) orderNumbers.append(orderNumber) # 投递任务到队列,拿到任务实例 job = q.enqueue(login_to_website, email, password, orderNumber) job_key = job.get_id() # 轮询等待Worker执行完成 max_wait_time = 25 # 预留5秒余量,适配Heroku 30秒请求超时阈值 waited_duration = 0 poll_interval = 0.5 # 每0.5秒查询一次任务状态,降低Redis请求压力 while waited_duration < max_wait_time: # 同步刷新任务的最新状态 job.refresh() # 任务执行成功,返回结果 if job.get_status() == 'finished': return jsonify({ "task_id": job_key, "status": "success", "result": job.result }) # 任务执行失败,返回错误信息 if job.get_status() == 'failed': return jsonify({ "task_id": job_key, "status": "failed", "error": str(job.exc_info) }) # 任务还在运行,进入休眠等待 time.sleep(poll_interval) waited_duration += poll_interval # 等待超时的兜底返回 return jsonify({ "task_id": job_key, "status": "timeout", "message": "任务超过最大等待时长,请稍后通过任务ID查询执行结果" })
关键注意事项
- 严格控制最大等待时长:Heroku平台对Web请求的最长允许处理时间是30秒,超过这个阈值平台会主动断开请求连接,所以等待上限必须留足余量,设置在25秒以内。
- 轮询间隔不要过短:保持0.5-1秒的查询间隔即可,过短的查询频率会给Redis服务带来不必要的压力,也会额外消耗Web进程的运行时长。
- 注意全局变量的线程安全问题:你当前代码里用全局列表
orderNumbers存储临时订单号,多请求并发时会出现数据互相覆盖的问题,后续可以把这类临时数据存在任务的元数据或者Redis缓存中,不要依赖进程内的全局变量存请求级数据。 - 不要跳过任务状态刷新步骤:拿到的初始job对象是入队时的快照,不调用
job.refresh()同步最新状态的话,会一直拿到入队时的初始状态,陷入死循环。
内容的提问来源于stack exchange,提问作者nader sayed
相关产品推荐
相关产品推荐

