You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何通过asyncio在监听Webhook端口时异步执行耗时任务?

如何通过asyncio在监听Webhook端口时异步执行耗时任务?

嘿,我完全懂你的困扰——不想让耗时的API调用拖慢webhook的监听,还想尽量用asyncio而不是额外引入threading模块对吧?其实是可以做到的,但得先理清几个关键点,再一步步来实现。

首先要明确:普通的Flask是同步Web框架,哪怕你在里面写asyncio代码,也没法真正实现异步请求处理,因为Flask默认的请求处理流程是同步阻塞的。不过好在Flask 2.0及以上版本支持异步视图,或者你也可以用更原生支持asyncio的FastAPI,这两个都能满足你的需求。

方案一:用Flask 2.0+的异步视图配合asyncio

核心思路是:把webhook视图改成异步函数,然后用asyncio.create_task()把耗时的API调用任务丢进事件循环,让它在后台异步执行,而视图函数可以立即返回响应,不会阻塞后续的webhook请求。

注意:这里必须用异步的HTTP库(比如aiohttp)来调用外部API,不能用requests这种同步库——同步IO会直接阻塞整个asyncio事件循环,等于白忙活。

示例代码如下:

from flask import Flask, request, abort
import asyncio
import aiohttp

app = Flask(__name__)

# 定义耗时的异步任务:调用外部API
async def process_external_api():
    async with aiohttp.ClientSession() as session:
        # 替换成你实际要调用的API地址
        async with session.get("https://your-external-server.com/api") as resp:
            # 处理API返回结果,比如存数据库、打印日志等
            data = await resp.json()
            print(f"Received data from API: {data}")

@app.route("/", methods=["POST"])
async def webhook():
    if request.method != "POST":
        abort(405)
    
    # 启动异步任务,不等待它完成就继续执行
    asyncio.create_task(process_external_api())
    
    # 立即返回202 Accepted响应,告诉发送方请求已接收
    return {"status": "request accepted and processing"}, 202

方案二:用FastAPI(更原生支持asyncio)

如果你愿意换框架,FastAPI是更好的选择——它从底层就基于asyncio开发,异步支持更彻底,代码也更简洁:

from fastapi import FastAPI, Request
import asyncio
import aiohttp

app = FastAPI()

async def process_external_api():
    async with aiohttp.ClientSession() as session:
        async with session.get("https://your-external-server.com/api") as resp:
            data = await resp.json()
            print(f"API response data: {data}")

@app.post("/")
async def webhook(request: Request):
    # 启动后台异步任务
    asyncio.create_task(process_external_api())
    return {"status": "processing in background"}, 202

关键原理说明

为什么这样不会阻塞监听?

  • asyncio的事件循环会管理所有异步任务:当process_external_api()在等待外部API响应时,事件循环会暂时挂起这个任务,转而处理新的webhook请求(或者其他异步任务)。
  • asyncio.create_task()相当于把耗时任务“丢进后台”,视图函数不用等它完成就能返回响应,这样webhook可以立刻准备接收下一个请求。

注意事项

  • 绝对不要在异步任务里用同步IO操作(比如requests、同步数据库驱动),否则会阻塞整个事件循环,和同步代码没区别。
  • 如果你的耗时任务是CPU密集型(比如大量计算),asyncio帮不上忙,这时候才需要用threading或multiprocessing。但你的场景是和服务器通信的API调用,属于IO密集型,asyncio正好适配。

内容来源于stack exchange

火山引擎 最新活动