PHP实现多进程

swoole 实现php多进程同步

PHP 本身是一个强领域的语言,主要应用于web开发。
PHP 也可以进行多进程开发,但是使用的第三方扩展。
下面我们演示使用 swoole 实现 PHP多进程,且自定义进程名称,可启动及停止。
自定义进程名前缀:tprocess-
主进程名为:tprocess-master
子进程名为:tprocess-xxx              xxx 为数字

停止进程有多种方式,比如 kill -9 强制杀死,但这样会导致任务在中间中断,出现脏数据
我们使用信号的方式,通知子进程,在下一个任务时退出。

在使用多进程时,容易出现僵尸进程,为了避免僵尸进程,我们使用 信号接收子进程退消息,并回收资源。

运行

nohup php -f tproc.php start &

停止,会发送信号给运行的主进程,由主进程通知子进程结束

php -f tproc.php stop

启动后效果如下:

[[email protected] test]$ ps -ef | grep tprocess
jingwu   10126  4844  0 00:16 pts/5    00:00:00 tprocess-master
jingwu   10127 10126  0 00:16 pts/5    00:00:00 tprocess-0
jingwu   10128 10126  0 00:16 pts/5    00:00:00 tprocess-1
jingwu   10129 10126  0 00:16 pts/5    00:00:00 tprocess-2
jingwu   10130 10126  0 00:16 pts/5    00:00:00 tprocess-3
jingwu   10131 10126  0 00:16 pts/5    00:00:00 tprocess-4

tproc.php

error_reporting(E_ALL);
ini_set(‘display_errors‘, ‘1‘);
ini_set(‘error_log‘, ‘/tmp/tprocess_error.log‘);

define(‘PROC_LIMIT‘, 5);

class ProcConfig {
    static $status = null;
}   

//查找对应的进程,我们直接查找系统 /proc 目录下的文件
//这样做是因为,在生产环境不一定会开放 exec 等函数,有一定的局限
//查找系统文件还可以避免维护进程ID文件
function proc_find() {
    $baseDir = ‘/proc‘;
    $rows = scandir(‘/proc‘);
    $procTitles = [];
    foreach($rows as $pid) {
        if(!is_numeric($pid)) continue;
        $cmdlineFile = sprintf("%s/%s/cmdline", $baseDir, $pid);
        if(!file_exists($cmdlineFile)) continue;
        $title = trim(file_get_contents($cmdlineFile));
        if(substr($title, 0, 9) != ‘tprocess-‘) continue;
        $procTitles[$title] = $pid;
    }
    return $procTitles;
}   

//检查子进程,因异常或任务结束而导致子进程结束
//通过检查,维持一定数量的子进程
function proc_check() {
    $titles = [‘ip‘ => [], ‘domain‘ => []];
    for($i = 0; $i < PROC_LIMIT; $i++) $titles[‘ip‘][] = [‘tprocess-‘.$i, $i];

    $procs = proc_find();
    foreach($titles as $key => $items) {
        foreach($items as $row) {
            $title = $row[0];
            $index = $row[1];
            if(isset($procs[$title])) continue;
            $worker = new swoole_process(function (swoole_process $process) use($index) {proc_child($process, $index);}, true);
            $procid = $worker->start();
        }
    }
}

//守护进程,负责启动及监控子进程
function proc_master() {
    $procs = proc_find();
    if(isset($procs[‘tprocess-master‘])) {
        print("Dispatch[running]守护进程已经启动\n");
        exit(0);
    }
    //主进程异常结束,子进程未结束,结束所有子进程
    if(!isset($procs[‘tprocess-master‘]) && $procs) {
        foreach($procs as $title => $pid) posix_kill($pid, 9);
    }

    //设置主进程名
    swoole_set_process_name(‘tprocess-master‘);
}    

//worker进程,负责处理数据
function proc_child(swoole_process $process, $index) {
    $title = ‘tprocess-‘.$index;
    $process->name($title);
    while(1) {
        if(ProcConfig::$status->get()) exit(1);
        sleep(5);
    }
}

$action = isset($argv[1]) ? $argv[1] : ‘‘;
if($action == "start") {
    //进程状态位,用于标识是否可以退出
    ProcConfig::$status = new swoole_atomic(0);

    proc_master();
    print("started worker\n");
    sleep(2);
    proc_check();

    //注册子进程退出监听函数,避免僵尸进程
    swoole_process::signal(SIGCHLD, function($sig) {
        while ($ret =  swoole_process::wait(false)) {
            file_put_contents(‘/tmp/tprocess_defunct.log‘, "child process killed: {$sig}-{$ret[‘pid‘]}\n", FILE_APPEND);
            proc_check();
        }
    });

    //主进程监听 SIGUSR2 信号,并设置进程状态位,通知子进程结束
    swoole_process::signal(SIGUSR2, function($sig) {
        ProcConfig::$status->add(1);
        print("receive SIGUSR2 to stop worker\n");
        exit(0);
    });

}else if($action == "stop") {
    $procs = proc_find();
    if(isset($procs[‘tprocess-master‘])) {
        posix_kill($procs[‘tprocess-master‘], SIGUSR2);
    }
    print("stop disptch worker is ok\n");
    exit(0);
} else {
    echo <<< EOF
 cmd [action]

 action list:
     start
     stop

 eg:
     php -f ./tproc.php start
     php -f ./tproc.php stop

EOF;
} 

原文地址:http://blog.51cto.com/jingwu/2064035

时间: 2024-11-09 17:55:03

PHP实现多进程的相关文章

C#:多进程开发,控制进程数量

正在c#程序优化时,如果多线程效果不佳的情况下,也会使用多进程的方案,如下: System.Threading.Tasks.Task task=System.Threading.Tasks.Task.Factory.StartNew( (object mystate) => { Process process = Process.Start("AutoCollectMrMultipleProcess.exe", mystate.ToString()); process.WaitF

多线程和多进程的区别与联系

1.单进程单线程:一个人在一个桌子上吃菜.2.单进程多线程:多个人在同一个桌子上一起吃菜.3.多进程单线程:多个人每个人在自己的桌子上吃菜. 多线程的问题是多个人同时吃一道菜的时候容易发生争抢,例如两个人同时夹一个菜,一个人刚伸出筷子,结果伸到的时候已经被夹走菜了...此时就必须等一个人夹一口之后,在还给另外一个人夹菜,也就是说资源共享就会发生冲突争抢. 1.对于 Windows 系统来说,[开桌子]的开销很大,因此 Windows 鼓励大家在一个桌子上吃菜.因此 Windows 多线程学习重点

Python有了asyncio和aiohttp在爬虫这类型IO任务中多线程/多进程还有存在的必要吗?

最近正在学习Python中的异步编程,看了一些博客后做了一些小测验:对比asyncio+aiohttp的爬虫和asyncio+aiohttp+concurrent.futures(线程池/进程池)在效率中的差异,注释:在爬虫中我几乎没有使用任何计算性任务,为了探测异步的性能,全部都只是做了网络IO请求,就是说aiohttp把网页get完就程序就done了. 结果发现前者的效率比后者还要高.我询问了另外一位博主,(提供代码的博主没回我信息),他说使用concurrent.futures的话因为我全

多线程还是多进程的选择及区别

对比维度 多进程 多线程 总结 数据共享.同步 数据共享复杂,需要用IPC:数据是分开的,同步简单 因为共享进程数据,数据共享简单,但也是因为这个原因导致同步复杂 各有优势 内存.CPU 占用内存多,切换复杂,CPU利用率低 占用内存少,切换简单,CPU利用率高 线程占优 创建销毁.切换 创建销毁.切换复杂,速度慢 创建销毁.切换简单,速度很快 线程占优 编程.调试 编程简单,调试简单 编程复杂,调试复杂 进程占优 可靠性 进程间不会互相影响 一个线程挂掉将导致整个进程挂掉 进程占优 分布式 适

python 之 多进程

阅读目录 1. Process 2. Lock 3. Semaphore 4. Event 5. Queue 6. Pipe 7. Pool 序. multiprocessingpython中的多线程其实并不是真正的多线程,如果想要充分地使用多核CPU的资源,在python中大部分情况需要使用多进程.Python提供了非常好用的多进程包multiprocessing,只需要定义一个函数,Python会完成其他所有事情.借助这个包,可以轻松完成从单进程到并发执行的转换.multiprocessin

python logging 多进程写兼容模块

logging中RotatingFileHandler和TimedRotatingFileHandler对于多进程不支持(由于每个进程都保持一个固定的文件句柄,导致在达到条件回滚时,相互之间的rename会相互干扰,比如一个进程已经把worker.log变为worker.log.2016-06-01了,其他进程就跟着写到worker.log.2016-06-01了,其他还有好多问题) 故实现适应多进程的handle,代码如下: # -*- coding: utf-8 -*- import log

Python 3 并发编程多进程之队列(推荐使用)

Python 3 并发编程多进程之队列(推荐使用) 进程彼此之间互相隔离,要实现进程间通信(IPC),multiprocessing模块支持两种形式:队列和管道,这两种方式都是使用消息传递的. 可以往队列里放任意类型的数据 创建队列的类(底层就是以管道和锁定的方式实现): 1 Queue([maxsize]):创建共享的进程队列,Queue是多进程安全的队列,可以使用Queue实现多进程之间的数据传递. 参数介绍: 1 maxsize是队列中允许最大项数,省略则无大小限制. 方法介绍: 1.主要

python自动化运维之多进程

python中的多线程其实并不是真正的多线程,如果想要充分地使用多核CPU的资源,在python中大部分情况需要使用多进程.Python提供了非常好用的多进程包multiprocessing,只需要定义一个函数,Python会完成其他所有事情.借助这个包,可以轻松完成从单进程到并发执行的转换.multiprocessing支持子进程.通信和共享数据.执行不同形式的同步,提供了Process.Queue.Pipe.Lock等组件.1.Process创建进程的类:Process([group[,ta

python 学习总结2 多进程

多进程: 我们什么时候需要多进程呢?我们知道python的多线程,实际不是真实的多线程,它同一时间在一个cpu执行一个任务,它通过上下文的切换来让我看起来是多并发的, 那么如果我们想要真正实现多个任务在多个cpu上同时执行,我们就需要多进程的性质来帮忙了(python的多线程不适合cpu密集型的任务,适合io密集型的任务). import multiprocessing import threading def thread_run(): print(threading.get_ident())

多进程与多线程差别

 在Unix上编程採用多线程还是多进程的争执由来已久,这样的争执最常见到在C/S通讯中服务端并发技术 的选型上,比方WEBserver技术中.Apache是採用多进程的(perfork模式,每客户连接相应一个进程,每进程中仅仅存在唯一一个运行线程), Java的Web容器Tomcat.Websphere等都是多线程的(每客户连接相应一个线程,全部线程都在一个进程中). 从Unix发展历史看,伴随着Unix的诞生进程就出现了.而线程非常晚才被系统支持,比如Linux直到内核2.6.才支持符合P