陈泽达 發表於 2026-5-3 17:22:40

php调用Workerman管理定时任务详解

<div id="navCategory"><h5 class="catalogue">目录</h5><ul class="first_class_ul"><li><a href="#_label0">1. 启动定时任务</a></li><li><a href="#_label1">2. 停止定时任务</a></li><li><a href="#_label2">3. 重启定时任务</a></li><li><a href="#_label3">4. 多进程环境注意事项</a></li><li><a href="#_label4">5. 通过命令行管理 Worker</a></li><li><a href="#_label5">6. 动态控制定时任务(高级)</a></li><li><a href="#_label6">7. 注意事项</a></li><li><a href="#_label7">总结</a></li></ul></div><p>在 Workerman 中管理定时任务(启动、重启、停止)需要结合 Timer 类和 Worker 进程的生命周期。以下是详细操作步骤:</p>
<p class="maodian"><a name="_label0"></a></p><h2>1. 启动定时任务</h2>
<p>定时任务通常在 onWorkerStart 回调中注册,Worker 进程启动后自动执行。</p>
<p>代码示例</p>
<div class="jb51code"><pre class="brush:php;">use Workerman\Worker;
use Workerman\Timer;

require_once __DIR__ . '/vendor/autoload.php';

$worker = new Worker();

// Worker 进程启动时注册定时任务
$worker-&gt;onWorkerStart = function ($worker) {
    // 启动一个每秒执行的定时任务
    $timerId = Timer::add(1, function () {
      echo "Running task at " . date('Y-m-d H:i:s') . "\n";
    });
   
    // 保存定时器 ID(用于后续操作)
    $worker-&gt;timerId = $timerId;
};

Worker::runAll();</pre></div>
<p class="maodian"><a name="_label1"></a></p><h2>2. 停止定时任务</h2>
<p>通过 Timer::del() 方法停止指定定时器。</p>
<p>代码示例</p>
<div class="jb51code"><pre class="brush:php;">// 停止单个定时任务
$timerId = Timer::add(2, function () { /* ... */ });
Timer::del($timerId);

// 停止所有定时任务
Timer::delAll(); // 慎用!会停止当前进程所有定时器
动态停止示例
$worker-&gt;onMessage = function ($connection, $data) use ($worker) {
    // 收到特定指令时停止定时任务
    if ($data === 'stop') {
      Timer::del($worker-&gt;timerId);
      $connection-&gt;send("定时任务已停止");
    }
};
</pre></div>
<p class="maodian"><a name="_label2"></a></p><h2>3. 重启定时任务</h2>
<p>重启需要先停止旧任务,再重新注册新任务。</p>
<p>代码示例</p>
<div class="jb51code"><pre class="brush:php;">// 假设 $oldTimerId 是已存在的定时器 ID
$newTimerId = Timer::add(5, function () { /* 新任务逻辑 */ });
Timer::del($oldTimerId); // 停止旧任务

// 或通过闭包动态更新
$worker-&gt;onWorkerStart = function ($worker) {
    $worker-&gt;timerId = Timer::add(1, function () use ($worker) {
      static $count = 0;
      $count++;
      echo "执行次数: $count\n";
      
      // 达到条件后重启任务(例如修改间隔时间)
      if ($count &gt;= 5) {
            Timer::del($worker-&gt;timerId);
            $worker-&gt;timerId = Timer::add(2, function () {
                echo "重启后的任务\n";
            });
      }
    });
};</pre></div>
<p class="maodian"><a name="_label3"></a></p><h2>4. 多进程环境注意事项</h2>
<p>单例任务:如果只需要一个进程运行定时任务,在 onWorkerStart 中通过进程 ID 控制:</p>
<div class="jb51code"><pre class="brush:php;">$worker-&gt;onWorkerStart = function ($worker) {
    if ($worker-&gt;id === 0) { // 仅第一个进程执行
      Timer::add(1, function () { /* ... */ });
    }
};
</pre></div>
<p>分布式部署:多台服务器时,使用 Redis 锁或数据库标记确保任务唯一性。</p>
<p class="maodian"><a name="_label4"></a></p><h2>5. 通过命令行管理 Worker</h2>
<p>Workerman 的定时任务依赖于 Worker 进程,因此可通过管理 Worker 间接控制定时任务:</p>
<table><tbody><tr><th>操作</th><th>命令</th><th>说明</th></tr><tr><td>启动</td><td>php yourfile.php start</td><td>启动 Worker 进程,定时任务自动运行</td></tr><tr><td>平滑重启</td><td>php yourfile.php reload</td><td>重新加载业务代码,定时任务会重新初始化</td></tr><tr><td>强制停止</td><td>php yourfile.php stop</td><td>停止所有 Worker 进程(立即终止)</td></tr><tr><td>优雅停止</td><td>php yourfile.php stop -g</td><td>等待当前任务完成后再停止</td></tr></tbody></table>
<p class="maodian"><a name="_label5"></a></p><h2>6. 动态控制定时任务(高级)</h2>
<p>结合 HTTP 接口或自定义信号动态管理:</p>
<p>示例:通过 HTTP 接口控制</p>
<div class="jb51code"><pre class="brush:php;">$httpWorker = new Worker('http://0.0.0.0:8080');
$httpWorker-&gt;onMessage = function ($connection, $request) {
    $action = $request-&gt;get('action');
   
    switch ($action) {
      case 'start':
            $timerId = Timer::add(1, function () { /* ... */ });
            $connection-&gt;send("定时任务 ID: $timerId");
            break;
      case 'stop':
            $timerId = $request-&gt;get('timer_id');
            Timer::del($timerId);
            $connection-&gt;send("已停止任务");
            break;
    }
};</pre></div>
<p>示例:通过信号控制</p>
<div class="jb51code"><pre class="brush:php;">// 注册自定义信号
Worker::$onMasterReload = function () {
    // 收到 SIGUSR1 信号时重启某个任务
    Timer::del($oldTimerId);
    $newTimerId = Timer::add(3, function () { /* ... */ });
};
</pre></div>
<p class="maodian"><a name="_label6"></a></p><h2>7. 注意事项</h2>
<p>持久化存储:定时器 ID 保存在内存中,进程重启后会丢失,需外部存储(如 Redis)记录关键任务状态。</p>
<p>原子操作:多进程操作时,使用锁机制避免竞争条件。</p>
<p>异常处理:</p>
<div class="jb51code"><pre class="brush:php;">Timer::add(1, function () {
    try {
      // 业务逻辑
    } catch (Throwable $e) {
      echo "定时任务异常: " . $e-&gt;getMessage();
    }
});</pre></div>
<p class="maodian"><a name="_label7"></a></p><h2>总结</h2>
<table><tbody><tr><th>操作</th><th>方法</th><th>场景</th></tr><tr><td>启动</td><td>Timer::add()</td><td>Worker 启动时自动注册</td></tr><tr><td>停止</td><td>Timer::del()&nbsp;或&nbsp;Timer::delAll()</td><td>动态终止指定或全部任务</td></tr><tr><td>重启</td><td>先&nbsp;del()&nbsp;再&nbsp;add()</td><td>修改间隔时间或任务逻辑</td></tr><tr><td>全局控制</td><td>命令行&nbsp;start/stop/reload</td><td>管理整个 Worker 进程生命周期</td></tr></tbody></table>
頁: [1]
查看完整版本: php调用Workerman管理定时任务详解