Workerman定时器任务管理

在 Workerman 中管理定时任务(启动、重启、停止)需要结合 Timer 类和 Worker 进程的生命周期。以下是详细操作步骤:


1. 启动定时任务

定时任务通常在 onWorkerStart 回调中注册,Worker 进程启动后自动执行。

代码示例
use Workerman\Worker;
use Workerman\Timer;

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

$worker = new Worker();

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

Worker::runAll();

2. 停止定时任务

通过 Timer::del() 方法停止指定定时器。

代码示例
// 停止单个定时任务
$timerId = Timer::add(2, function () { /* ... */ });
Timer::del($timerId);

// 停止所有定时任务
Timer::delAll(); // 慎用!会停止当前进程所有定时器
动态停止示例
$worker->onMessage = function ($connection, $data) use ($worker) {
    // 收到特定指令时停止定时任务
    if ($data === 'stop') {
        Timer::del($worker->timerId);
        $connection->send("定时任务已停止");
    }
};

3. 重启定时任务

重启需要先停止旧任务,再重新注册新任务。

代码示例
// 假设 $oldTimerId 是已存在的定时器 ID
$newTimerId = Timer::add(5, function () { /* 新任务逻辑 */ });
Timer::del($oldTimerId); // 停止旧任务

// 或通过闭包动态更新
$worker->onWorkerStart = function ($worker) {
    $worker->timerId = Timer::add(1, function () use ($worker) {
        static $count = 0;
        $count++;
        echo "执行次数: $count\n";
        
        // 达到条件后重启任务(例如修改间隔时间)
        if ($count >= 5) {
            Timer::del($worker->timerId);
            $worker->timerId = Timer::add(2, function () { 
                echo "重启后的任务\n"; 
            });
        }
    });
};

4. 多进程环境注意事项

  • 单例任务:如果只需要一个进程运行定时任务,在 onWorkerStart 中通过进程 ID 控制:

    $worker->onWorkerStart = function ($worker) {
        if ($worker->id === 0) { // 仅第一个进程执行
            Timer::add(1, function () { /* ... */ });
        }
    };

  • 分布式部署:多台服务器时,使用 Redis 锁或数据库标记确保任务唯一性。


5. 通过命令行管理 Worker

Workerman 的定时任务依赖于 Worker 进程,因此可通过管理 Worker 间接控制定时任务:

操作 命令 说明
启动 php yourfile.php start 启动 Worker 进程,定时任务自动运行
平滑重启 php yourfile.php reload 重新加载业务代码,定时任务会重新初始化
强制停止 php yourfile.php stop 停止所有 Worker 进程(立即终止)
优雅停止 php yourfile.php stop -g 等待当前任务完成后再停止

6. 动态控制定时任务(高级)

结合 HTTP 接口或自定义信号动态管理:

示例:通过 HTTP 接口控制
$httpWorker = new Worker('http://0.0.0.0:8080');
$httpWorker->onMessage = function ($connection, $request) {
    $action = $request->get('action');
    
    switch ($action) {
        case 'start':
            $timerId = Timer::add(1, function () { /* ... */ });
            $connection->send("定时任务 ID: $timerId");
            break;
        case 'stop':
            $timerId = $request->get('timer_id');
            Timer::del($timerId);
            $connection->send("已停止任务");
            break;
    }
};
示例:通过信号控制
// 注册自定义信号
Worker::$onMasterReload = function () {
    // 收到 SIGUSR1 信号时重启某个任务
    Timer::del($oldTimerId);
    $newTimerId = Timer::add(3, function () { /* ... */ });
};

7. 注意事项

  1. 持久化存储:定时器 ID 保存在内存中,进程重启后会丢失,需外部存储(如 Redis)记录关键任务状态。

  2. 原子操作:多进程操作时,使用锁机制避免竞争条件。

  3. 异常处理

    Timer::add(1, function () {
        try {
            // 业务逻辑
        } catch (Throwable $e) {
            echo "定时任务异常: " . $e->getMessage();
        }
    });


总结

操作 方法 场景
启动 Timer::add() Worker 启动时自动注册
停止 Timer::del() 或 Timer::delAll() 动态终止指定或全部任务
重启 先 del() 再 add() 修改间隔时间或任务逻辑
全局控制 命令行 start/stop/reload 管理整个 Worker 进程生命周期

你可能感兴趣的:(php,php)