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

PHP Laravel Horizon:如何终止特定运行中的任务?

如何终止Horizon中运行的单个长时间任务?

针对Horizon里出现性能问题或资源竞争的长时间任务,你试过的几种方案确实存在局限性,这里给几个更精准的解决办法:

方案1:通过任务标签定位并终止进程

这是最直接的方式,前提是给任务打了唯一标识的标签:

  • 在任务类中定义标签,关联任务唯一ID:
    class LongRunningTask implements ShouldQueue
    {
        public $tags = [];
    
        public function __construct(int $taskId)
        {
            $this->tags = ["long-task:{$taskId}"];
        }
    
        // ... 任务逻辑
    }
    
  • 执行命令列出所有Horizon进程及对应标签:
    php artisan horizon:list
    
  • 找到目标任务对应的进程ID,发送优雅终止信号(让任务有机会清理资源):
    kill -TERM <进程ID>
    
    如果任务无响应,再用强制终止信号(不推荐,可能丢失未提交的数据):
    kill -KILL <进程ID>
    

方案2:自定义任务内终止逻辑(安全优先)

如果不想通过杀进程的方式,可在任务里加入主动检查终止标记的逻辑:

  • 在任务的处理方法中,周期性检查外部终止信号(比如用Redis存储标记):
    public function handle()
    {
        $terminateKey = "terminate:{$this->taskId}";
        while (true) {
            // 检查是否收到终止指令
            if (\Illuminate\Support\Facades\Redis::get($terminateKey)) {
                \Illuminate\Support\Facades\Redis::del($terminateKey);
                $this->info("任务{$this->taskId}已主动终止");
                return;
            }
    
            // 执行单次任务逻辑步骤
            $this->processTaskStep();
        }
    }
    
  • 需要终止任务时,只需设置对应的Redis键即可:
    php artisan tinker
    >>> Redis::set('terminate:123', 1);
    

方案3:定位无标签的已运行任务

如果任务没打标签,可通过进程命令行信息定位:

  • 执行命令筛选Horizon的worker进程:
    ps aux | grep horizon:worker
    
  • 查看每个进程的命令行参数,里面会包含任务类名(比如App\Jobs\LongRunningTask),找到目标任务对应的进程ID后,用kill命令终止。

注意事项

  • 优先使用优雅终止信号-TERM,避免强制终止导致数据不一致
  • 不要随意执行artisan horizon:clear,该命令会清空所有待处理任务,且无法终止正在运行的进程
  • 给任务打标签是长期的最佳实践,方便后续快速定位和管理任务

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 08:42:10