You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Django REST Framework实现异步长请求处理需求

处理长耗时请求:立即返回200+异步返回结果的实现方案

核心逻辑

先返回200 OK确认请求已接收,后台异步执行长任务,后续通过回调、轮询或推送方式把结果给到客户端。

1. 回调URL机制

  • 客户端发起请求时,携带一个自身可接收请求的回调URL
  • 服务端收到请求后立刻返回200响应,同时启动异步线程处理任务
  • 任务完成后,服务端主动调用回调URL,把结果发送过去
  • 伪代码示例(Python):
from fastapi import FastAPI
import asyncio
import requests

app = FastAPI()

# 接收长任务请求
@app.post("/long-task")
async def accept_task(callback_url: str):
    # 启动异步任务
    asyncio.create_task(handle_long_task(callback_url))
    return {"status": "accepted", "msg": "任务已启动,完成后将回调通知"}

# 异步处理长任务
async def handle_long_task(callback_url):
    # 模拟3分钟以上的耗时操作
    await asyncio.sleep(190)
    task_result = {"data": "长任务处理完成的结果"}
    # 调用回调URL推送结果
    requests.post(callback_url, json=task_result)

2. 轮询查询机制

  • 服务端收到请求后生成唯一任务ID,返回200的同时把ID给到客户端
  • 客户端拿到ID后,定期调用查询接口获取任务状态
  • 任务完成时,查询接口直接返回处理结果
  • 伪代码示例(Java):
import org.springframework.web.bind.annotation.*;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

@RestController
public class LongTaskController {
    private final ExecutorService executor = Executors.newFixedThreadPool(5);
    private final Map<String, String> taskResults = new ConcurrentHashMap<>();

    // 启动长任务
    @PostMapping("/long-task")
    public Map<String, String> startTask() {
        String taskId = UUID.randomUUID().toString();
        executor.submit(() -> {
            // 模拟长耗时操作
            try {
                Thread.sleep(190000);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
            taskResults.put(taskId, "长任务处理完成的结果");
        });
        return Map.of("taskId", taskId, "status", "running");
    }

    // 查询任务结果
    @GetMapping("/task-result/{taskId}")
    public Map<String, Object> getResult(@PathVariable String taskId) {
        if (!taskResults.containsKey(taskId)) {
            return Map.of("status", "pending");
        }
        return Map.of("status", "completed", "result", taskResults.get(taskId));
    }
}

3. WebSocket实时推送

  • 客户端先与服务端建立WebSocket连接
  • 发送长任务请求后,服务端立即返回200,同时通过WebSocket告知任务启动
  • 任务完成后,直接通过WebSocket把结果推送给客户端
  • 伪代码示例(前端JS):
// 建立WebSocket连接
const socket = new WebSocket('ws://your-server-domain/ws');

socket.onopen = () => {
    // 发送长任务请求
    fetch('/long-task', { method: 'POST' })
        .then(res => res.json())
        .then(data => console.log(data.msg));
};

// 接收服务端推送的结果
socket.onmessage = (event) => {
    const message = JSON.parse(event.data);
    if (message.type === 'task_done') {
        console.log('任务结果:', message.result);
        socket.close();
    }
};

关键注意点

  • 异步任务状态要持久化,比如存数据库或缓存,避免服务重启丢失任务信息
  • 要处理任务失败场景,及时通过对应渠道通知客户端错误详情
  • 回调URL需保证客户端能稳定接收,必要时加重试机制
  • 轮询间隔要合理,避免过短增加服务端压力,过长影响体验

内容的提问来源于stack exchange,提问作者Silverwing

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 20:00:58