PHP 进程池与轮询调度算法实现多任务的示例代码

phper 请了解进程调度策略,CPU 时间片,进程控制【创建,销毁,回收,进程信号】与及进程运行流程和基本的进程组,信号中断原理,以及进程之间的关系。

关于进程的更多内容可参考本人前面撸过的文章或是百度了解。

进程的通信:

匿名管道,命名管道,消息队列,内存共享,socketpair 请自行撸代码测试哦

进程的调度算法:

轮询,随机分发,计分板等策略或是搞个优先极或是队列,或是堆栈等基本的算法【自己去发挥哦】

进程池:

撸过 tcp 的话应该知道要能处理多个客户端,就得用 IO 复用技术【事件多路分发器】或是多进程以及多线程,每来一个客户端就 fork 一个进程或是线程,那样的话上下文切换成本特别高,所以咱们先创建好一组进程【进程池】,等客户端连接上来的时候,通过某种算法【我们用的轮询】来选择某个进程投递任务来干活,这样的话就不用创建又销毁来回折腾了,提升它的效率。下面是 PHP 代码版本的实现

<?php
/**
 * Created by PhpStorm.
 * User: 1655664358@qq.com
 * Date: 2019/1/12
 * Time: 16:18
 */

$flag = 1;

class process
{
 public $pid;
 public $name;
 public $file;
 public $num;
}
class instance
{
 public $processIdx;
 public $proc = [];
 public $processNum;
}
function sigHandler($sigNo)
{
 global $flag;
 $flag = 0;
 echo "信号中断处理".PHP_EOL;
}
function processPool(instance &$instance,$num)
{

 if (!$instance||$num==0){
  fprintf(STDERR,"%s","参数错误");
  return 1;
 }
 $instance->processIdx = 0;
 $instance->processNum = $num;

 pcntl_signal(SIGINT,'sigHandler');
 pcntl_signal(SIGTERM,'sigHandler');

 $process = new process();
 for ($i=1;$i<=$num;$i++){
  $instance->proc[$i] = clone $process;
  $instance->proc[$i]->file = $i;
  $instance->proc[$i]->pid = pcntl_fork();
  $instance->processIdx = $i;
  if ($instance->proc[$i]->pid<0){
   exit("进程创建失败");
  }
  else if ($instance->proc[$i]->pid>0){
   //nothing
   continue;
  }else{

   worker($instance);
  }
 }
 master($instance);
 $exitProcess= [];
 while (1){
  for ($i=1;$i<=$num;$i++){
  //非阻塞方式回收子进程
   pcntl_waitpid($instance->proc[$i]->pid,$status,WNOHANG);
   if ($status){
    $exitProcess[] = $instance->proc[$i]->pid;
    fwrite(STDOUT,"worker#".$instance->proc[$i]->pid."-".$status,30);
   }
  }
  if (count($exitProcess)==$instance->processNum){
   exit(0);
  }
  usleep(1000);

 }

}
//简单的轮询算法 自己可以用队列,随机,链表,栈链,二叉树啥的折腾
function roundRobin(&$instance,$roll)
{
 /** @var instance $instance */
 return $instance->proc[$roll%$instance->processNum+1];
}

function master(&$instance)
{

 /** @var instance $instance */
 fprintf(STDOUT,"master 进程 %d\n",$instance->processIdx);
 global $flag;
 $roll = 0;
 while ($flag){
  pcntl_signal_dispatch();
  /** @var process $process */
  $process = roundRobin($instance,$roll++);
  echo "轮询的进程:".$process->pid.PHP_EOL;
  $file = $process->file;
  posix_mkfifo($file,0666);
  $fd = fopen($file,"w");
  fwrite($fd,"hi",2);
  sleep(1);

 }
 for ($i=1;$i<=$instance->processNum;$i++){
  posix_kill($instance->proc[$i]->pid,9);
 }
 fprintf(STDOUT,"master shutdown %d\n",$instance->processIdx);
}
function getProcess(&$instance)
{
 /** @var instance $instance */
 return $instance->proc[$instance->processIdx];
}
function worker(&$instance)
{
 /** @var process $process */
 $process = getProcess($instance);
 while (1){
  $file = $process->file;
  posix_mkfifo($file,0666);
  $fd = fopen($file,"r");
  $content = fread($fd,10);
  fprintf(STDOUT,"worker#%d读取的内容:%s file=%d\n",posix_getpid(),$content,$file);
 }
 exit(0);
}

$instance = new instance();
processPool($instance,5);

效果

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • PHP 多任务秒级定时器的实现方法

    描述 最近在公司部署crontab的时候,突发奇想是否可以用PHP去实现一个定时器,颗粒度到秒级就好,因为crontab最多到分钟级别,同时也调研了一下用PHP去实现的定时器还真不太多,Swoole 扩展里面到实现了一个毫秒级的定时器很高效,但毕竟不是纯PHP代码写的,所以最后还是考虑用PHP去实现一个定时器类,以供学习参考. 实现 在实现定时器代码的时候,用到了PHP系统自带的两个扩展 Pcntl - 多进程扩展 : 主要就是让PHP可以同时开启很多子进程,并行的去处理一些任务. Spl -

  • PHP中使用协同程序实现合作多任务第1/2页

    PHP5.5一个比较好的新功能是实现对生成器和协同程序的支持.对于生成器,PHP的文档和各种其他的博客文章(就像这一个或这一个)已经有了非常详细的讲解.协同程序相对受到的关注就少了,所以协同程序虽然有很强大的功能但也很难被知晓,解释起来也比较困难. 这篇文章指导你通过使用协同程序来实施任务调度,通过实例实现对技术的理解.我将在前三节做一个简单的背景介绍.如果你已经有了比较好的基础,可以直接跳到"协同多任务处理"一节. 生成器 生成器最基本的思想也是一个函数,这个函数的返回值是依次输出,

  • 基于PHP-FPM进程池探秘

    PHP 支持多进程而不支持多线程:PHP-FPM 在进程池中运行多个子进程并发处理所有连接请求.通过 ps 查看PHP-FPM进程池(pm.start_servers = 2)状态如下: root@d856fd02d2fe:~# ps aux -L USER PID LWP %CPU NLWP %MEM VSZ RSS TTY STAT START TIME COMMAND root 1 1 0.0 1 0.0 4504 692 ? Ss 13:10 0:00 /bin/sh /usr/loca

  • php多任务程序实例解析

    本文以实例简单解析了php多任务程序的实现方法,具体代码如下: <?php error_reporting(E_ALL); set_time_limit(0); /** * php多任务程序的实现 * 借助proc_open * 其实该叫进程(process) * 能启动多进程,你可以使用你的想象力做你想做的了,以后再写个能用的 * 如果你是在linux上跑php,并且启用pcntl模块后,使用pcntl函数该更好 * */ class Thread { protected $_pref; //

  • PHP 多进程与信号中断实现多任务常驻内存管理实例方法

    本文章基于 pcntl 扩展做的多进程测试. 进程调度策略 父子进程的调度由操作系统来负责,具体先调度子进程还是父进程由系统的调度算法决定,当然可以在父进程加上延时或是调用进程回收函数 pcntl_wait 可以先让子进程先运行,进程回收的目的是释放进程创建时占用的内存空间,防止变成僵尸进程. 信号: 信号称为软中断系统或是叫软中断,功能是向进程发送异步事件通知. 信号编号: [源码基于 SIGINT,SIGTERM,SIGUSR1 信号,含义请自行查看 kill 命令手册,不在描述] linu

  • PHP 进程池与轮询调度算法实现多任务的示例代码

    phper 请了解进程调度策略,CPU 时间片,进程控制[创建,销毁,回收,进程信号]与及进程运行流程和基本的进程组,信号中断原理,以及进程之间的关系. 关于进程的更多内容可参考本人前面撸过的文章或是百度了解. 进程的通信: 匿名管道,命名管道,消息队列,内存共享,socketpair 请自行撸代码测试哦 进程的调度算法: 轮询,随机分发,计分板等策略或是搞个优先极或是队列,或是堆栈等基本的算法[自己去发挥哦] 进程池: 撸过 tcp 的话应该知道要能处理多个客户端,就得用 IO 复用技术[事件

  • PHP实现长轮询消息实时推送功能代码实例讲解

    本文实例讲述了PHP实现的消息实时推送功能.分享给大家供大家参考,具体如下: 入口文件index.html <!DOCTYPE HTML> <html> <head> <title>反ajax推送</title> <style> .send{color:#555;text-align: left;} .require{color:blue;text-align: right;} .content_box{text-align: cen

  • Nginx反向代理+DNS轮询+IIS7.5 千万PV 百万IP 双线 网站架构案例

    Nginx  ("engine x") 是一个高性能的 HTTP 和反向代理服务器,也是一个 IMAP/POP3/SMTP 代理服务器. Nginx 是由 Igor Sysoev 为俄罗斯访问量第二的 Rambler.ru 站点开发的,它已经在该站点运行超过两年半了.Igor 将源代码以类BSD许可证的形式发布. Nginx 的中文维基:http://wiki.codemongers.com/NginxChs 在高并发连接的情况下,Nginx是Apache服务器不错的替代品.Nginx

  • Node.JS中事件轮询(Event Loop)的解析

    当我们知道I/O操作和创建新线程的开销是巨大的! 网站延迟的开销 对于一个网站,后台大多不需要进行复杂的计算,我们的程序大多时间花费在I/O读取上. 看到一个数据:IO操作可以比数据处理慢几个数量级.高端SSD固态硬盘的读取速度可以达到200mb-700mb/s;读取1000字节需要1.4微秒.而在此期间,2GHZ频率的CPU可以执行28000个指令处理周期.而网络数据的IO甚至更慢! NodeJS采用单线程非阻塞的架构解决老大难的IO问题 当采用多线程时,为每一个请求开启一个新的线程(Apac

  • linux下日志定时轮询的流程详解

    logrotate介绍 对于Linux系统安全来说,日志文件是极其重要的工具.日志文件包含了关于系统中发生的事件的有用信息,在排障过程中或者系统性能分析时经常被用到.当日志文件不断增长的时候,就需要定时切割,否则,写日志的速度和性能也会下降,更不便于我们归档,查询. 所以便有了使用logrotate的时候 ,logrotate是个十分有用的工具,它可以自动对日志进行截断(或轮循).压缩以及删除旧的日志文件.例如,你可以设置logrotate,让/var/log/foo日志文件每30天轮循,并删除

  • andriod如何搭建自己的轮询框架

    很多时候Android应用需要每间隔一段时间向服务器请求数据,如果服务器数据有更新则通知界面变化.Android中最常用的红点一般采用的就是轮询,红点是为了在数据有更新时及时的提醒用户,比如朋友圈更新,当用户的朋友圈更新时就会显示红点,就是通过移动端不断的向服务器查询朋友圈的更新状态. 相关知识点 在实现轮询框架时会主要会要到下面两个类,会结合轮询框架对这三个类进行讲解,在应用中分析会理解更加深刻. 1.IntentService IntentService是一种特殊的Service,继承了Se

  • 基于springboot 长轮询的实现操作

    springboot 长轮询实现 基于 @EnableAsync , @Sync @SpringBootApplication @EnableAsync public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } } @RequestMapping("/async") @RestControlle

  • Java 利用DeferredResult实现http轮询实时返回数据接口

    今天这篇文章呢,不难,其实是解答我一直以来心里的一个疑问.是这样的,之前看五八技术委员会主席沈剑老师的公众号架构师之路的一篇文章:http 如何像 tcp 一样实时的收消息,里面其中的一个方案是用 http 短连接轮询的方式实现"伪长连接".但是对于轮询,我们的第一反应肯定是有延时,但是标题不是说的是实时吗?当然我们可以把轮询的时长缩短一些,先不说这样大部分时间的轮询调用,可能都没消息返回,造成服务器资源浪费,轮询时间再短也是有延时啊,所以难道是伪实时?反正一般消息延时个三五秒,甚至十

  • Java 死锁解决方案顺序锁和轮询锁

    目录 死锁解决方案分析 解决方案1:顺序锁 解决方案2:轮询锁 总结 前言: 死锁(Dead Lock)指的是两个或两个以上的运算单元(进程.线程或协程),都在等待对方停止执行,以取得系统资源,但是没有一方提前退出,就称为死锁. 死锁示例代码如下: public class DeadLockExample { public static void main(String[] args) { Object lockA = new Object(); // 创建锁 A Object lockB =

  • Java servlet通过事件驱动进行高性能长轮询详解

    目录 servlet3.0的异步原理 使用servlet3.0实现长轮询 长轮询实现 servlet3.0的异步原理 servlet基础就不做介绍了,这里就介绍servlet3.0的一个重要的新特性:异步. servlet3.0原理图: tomcat接收到客户端的请求后会将请求AsyncContext交给业务线程,这样tomcat工作线程就能释放出来处理其它请求的连接. 业务线程池接收到AsyncContext后,就可以处理请求业务,完成业务逻辑后,根据AsyncContext获取respons

随机推荐