zoukankan      html  css  js  c++  java
  • SWOOLE 实现进程的守护

    一、 进程守护使用场景。

    后端经常会有类似这样的场景,某个脚本,需要不断的重复运行,这个时候,最好有一

    个守护程序,帮助我们不断地自动地拉起这些脚本进程,让它自动地重复运行。

    在 Linux/Unix 系统下,supervisor 就是使用 python 开发的一个优秀的进程管理工

    具,本文尝试使用 php 来实现类似的进程管理工具。

    二、swoole 的进程管理模块。

    php 的 swoole 扩展有一个进程管理模块,官方文档见:swoole 进程管理模块

    参考 supervisor 的实现方式,被守护的进程是作为 supervisor 的子进程来启动的,

    supervisor 通过监听子进程的信号,可实现对子进程的自动重启等功能。而 swoole

    的进程管理模块就提供了进程间通信的功能,可以实现对子进程的自动重启功能。

    三、第一个进程守护程序。

    要实现对子程序的守护,需要做到两点:

    1. 程序需要监听到子进程的结束信号,以便于重新拉起新的子进程。

    2. 子进程的运行环境需要独立于父进程。swoole 进程管理模块提供了一个 bool Process->exec(string $execfile, array

    $args) 方法,让子进程蜕变成另一个系统调用程序,同时还能保证父进程与当前进程

    仍然是父子进程关系。

    再通过 array Process::wait(bool $blocking = true) 方法,来等待子进程的退出信号。

    下面是使用 swoole 启动子进程,并回收子进程资源的示例代码:

    <?phpuse SwooleProcess;

    $php = "/usr/bin/env php";

    $script = dirname(__DIR__) . "/task.php";

    $command = "{$php} {$script}";

    $process = new Process(function (Process $worker) use ($command) {

    $worker->exec('/bin/sh', ['-c', $command]);

    });

    $pid = $process->start();

    printf("启动子进程 {$pid} ");

    while ($ret = Process::wait()) {

    $pid = intval($ret["pid"] ?? 0);

    printf("子进程 {$pid} 结束 ");}

    代码解析:

    $command 变量表示需要子进程脚本,通过 exec() 方法来启动成一个子进程的方式

    运行,再通过 Process::wait() 访求来等待 $command 这个子进程脚本结束,并回收

    进程资源。

    那么,只要在收到子进程的结束信号后,再起一个相同的子进程脚本,即可实现对子进

    程的守护了。于是,第一个守护子进程的程序实现代码:

    <?phpuse SwooleProcess;

    $php = "/usr/bin/env php";

    $script = dirname(__DIR__) . "/task.php";

    $command = "{$php} {$script}";

    do {

    $process = new Process(function (Process $worker) use ($command) {

    $worker->exec('/bin/sh', ['-c', $command]);

    });

    $pid = $process->start();

    printf("启动子进程 {$pid} ");

    } while (Process::wait());代码解析:

    这段代码只将启动子进程的逻辑加到一个死循环中,好让这个子进程脚本能够不断的重

    启。

    四、封装成类

    为了方便重用这段代码,可以将这段代码封装成一个简单的类:

    <?phpnamespace App;

    use SwooleProcess;

    class Daemon{

    /** @var string */

    private $command;

    public function __construct(string $command)

    {

    $this->command = $command;

    }

    public function run()

    {

    do {

    $process = new Process(function (Process $worker) {

    $worker->exec('/bin/sh', ['-c', $this->command]); });

    $pid = $process->start();

    } while (Process::wait());

    }

    }

    那么,这个 Daemon 类的使用方式如下:

    <?php

    use AppDaemon;

    $php = "/usr/bin/env php";

    $script = dirname(__DIR__) . "/task.php";

    $command = "{$php} {$script}";

    $daemon = new Daemon($command);

    $daemon->run();

    这个简单 Daemon 类虽然能实现对单个脚本进行重启守护,但是,如果我们有许多个

    脚本同时需要守护的,这个 Daemon 类显然是不能够满足需求的。

    有需要交流的小伙伴可以点击这里加本人QQ:luke

  • 相关阅读:
    8行代码批量下载GitHub上的图片
    python经典面试算法题1.1:如何实现链表的逆序
    pandas处理excel的常用方法技巧(上)
    numpy---python数据分析
    python、C++经典算法题:打印100以内的素数
    Java中数组、集合、链表、队列的数据结构和优缺点和他们之间的区别
    Hystrix
    Java中的static关键字解析
    Spring Boot
    Springcloud和Dubbo的区别。Eureka和Ribbon和Hystrix和zuul
  • 原文地址:https://www.cnblogs.com/starluke/p/13961290.html
Copyright © 2011-2022 走看看