
点击“停止生成”以后,页面不再增加文字,推理服务却继续生成。前端停止渲染、关闭 HTTP 连接和引擎移除任务发生在不同位置。诊断时需要用一个请求标识,把整条链路串起来。
本文引用 vLLM 0.10.2 V1 AsyncLLM 的接口说明,讨论自建应用与推理引擎的取消衔接。其他 vLLM 版本和远程兼容 API 需检查各自取消接口。配套程序是无 GPU 的生命周期实验。
一、用五个时间点定位断在哪里
| 时间点 | 需要记录的证据 |
|---|---|
| 用户停止 | 前端任务编号与用户动作时间 |
| 应用收到取消 | 经过身份核对的请求 ID 与取消原因 |
| 引擎收到 abort | 对应引擎 request_id、调用结果和错误 |
| 请求退出调度 | 请求级终态和活跃任务变化 |
| 资源可复用 | 后续请求可正常进入调度,缓存块与队列指标符合预期 |
前端可以使用 AbortController 终止 fetch。应用服务器还需处理客户端断开、代理超时和显式取消。若由后台任务继续读取上游响应,仅关闭浏览器连接可能不会结束该任务。经过网关和反向代理时,逐层记录取消传播时间。
二、为应用任务和引擎任务建立可核对的映射
在提交给引擎前登记请求,记录所属用户和工作进程。多副本应用要确保取消到达持有引擎任务的实例。取消接口先校验请求所有权,再找到对应的引擎 request_id。请求未注册时到达的取消也要被保留或拒绝为明确状态,避免随后启动任务。
vLLM 0.10.2 V1 AsyncLLM 提供异步 abort(request_id),其 generate 实现也处理 CancelledError 并触发清理。直接集成时检查当前版本的异常与迭代器关闭行为,避免另起任务后丢失取消信号。
参考资料 · vLLM 0.10.2 V1 AsyncLLM 源码与接口
三、在终止路径中清理引擎请求
下面是接入形态示意,engine 由应用初始化,sampling_params 和 prompt 来自已验证输入。request_id 应由服务端生成。此代码展示引擎迭代器生命周期,不包含完整 HTTP 端点和鉴权。
async def relay(engine, prompt, sampling_params, request_id):
iterator = engine.generate(prompt, sampling_params, request_id)
try:
async for output in iterator:
yield output
finally:
try:
await engine.abort(request_id)
finally:
await iterator.aclose()
调用方必须在连接断开或显式停止时,取消正在读取的任务并关闭 relay 迭代器。正常完成与取消会竞争,应采用单一终态转换,并在服务端日志保留取消到达顺序。清理失败需要告警和有界重试,取消仍在处理时不能提前宣称资源已经释放。重复取消不得影响其他请求。
四、先运行无 GPU 实验,再验证真实引擎
配套 cancel_demo.py 用集合模拟活跃任务,启动生成循环后取消应用任务。程序验证 finally 调用了引擎 abort,并关闭生成迭代器。运行 python cancel_demo.py 应打印 PASS。该实验能验证 Python 取消路径,不能测得 GPU 或 vLLM 的释放耗时。
真实引擎验收时,固定版本、模型、硬件和并发量,分别在排队中、生成中、自然完成前后、客户端断开后发起取消。记录请求级终态,确认不再生成新片段,并检查待处理和运行中请求数。再次发出短请求,确认服务能继续完成任务。
五、显存没有下降,应该怎么看?
推理服务通常预分配 KV Cache,CUDA 分配器也可能保留内存。任务结束后,内存可以变成引擎内部可复用空间,nvidia-smi 的进程显存仍可能保持高位。对照请求队列、调度状态、缓存指标和后续任务表现,比单看显存数字更能判断取消是否有效。
若请求取消后持续占用调度槽位,检查应用后台任务、代理断开传播、超时配置和引擎 abort 错误。对远程付费 API,停止读取后的服务端行为和费用按供应商规则核对,可参考本系列的 usage 对账文章。
验证范围:配套无 GPU 实验已验证任务取消到 abort 的调用链,当前未进行真实 GPU/vLLM 性能实验。正式上线需完成上面的排队、生成与完成竞态测试。
配套文件与同系列文章
下载本文 Python 示例 ZIP。技术文档核对日期为 2026 年 11 月 10 日。
汤不热吧