首页 » PHP教程 » php新过程技巧_深度PHP进程间通信商量

php新过程技巧_深度PHP进程间通信商量

访客 2024-11-07 0

扫一扫用手机浏览

文章目录 [+]

PHP作为阐明器运行通过线程或者进程都能实现(如果利用Apache,那么就可能利用多线程模型。
利用php-fpm,便是利用多进程模型,这里以多进程模型阐明)。
做事器每吸收到一个要求就要起一个PHP进程,均匀一个PHP进程花费内存2M旁边(默认最大为8M,参数可以设置)。
独立的进程让PHP能专一的做自己的阐明事情,程序员也从繁芜的代码逻辑中走出来,不用担心资源的竞争和各种锁问题。
独立进程虽好但这也导致想通过多进程或者异步来提速本钱非常的高(紧张是开拓难度)。
如果一定要通过PHP实现多进程和异步实在是很随意马虎做到的。

PHP有很多第三方扩展,比如Swoole能让PHP像Node一样实现异步。
PHP官方扩展库pcntl_能很大略的实现多进程。
扩展虽好,但实际运用时切忌要慎重,便利的同时风险也来了。
比如对多进程的掌握,处理不好很随意马虎导致程序去世锁,CPU内存爆表、做事器宕机。
异步回调的Coding办法与PHP本身的编程思想有一定出入,驾驭不好也是灾害。

php新过程技巧_深度PHP进程间通信商量

当然也不能说的太吓人,在实际的项目中我们有很多场景不得不考虑通过多进程或者异步来优化程序。
这里举一个很常见的例子『发送关照』,比如短信和邮件。
这里说一个实际的场景:企业须要给200W用户发短信关照,短信接口支持最大100次/秒的调用频率,短信接口每次调用耗时300毫秒。
如果单进程跑脚本的话,须要7天才能把短信发完。
如果我们起30个进程,每秒能发送100条短信,6个小时内能发完,能提速30倍。
优化方案确定之后,我们再看如何通过PHP去实现这样一个脚本。

php新过程技巧_深度PHP进程间通信商量
(图片来自网络侵删)

一. pcntl扩展初探;

通过pcntl扩展创建多进程,拜会如下代码;

function demo(array $phoneList){

$cnt = count($phoneList); //测试数组大小

$slice = 30; //须要调用的进程数量

$master = array_chunk($phoneList,floor($cnt/$slice));

$childList = []; while($slice >= 0)

{

$pid = pcntl_fork(); if($pid > 0){

$childList[$pid] = 1; //$pid>0表示当前还在实行父进程的代码

//这里最好啥都不做,每次实行pcntl_fork都会实行这里的代码。

//这里的代码实行完之后 会将$pid设置为0,然后jump到pcntl_fork代码之后,重新做判断;

}elseif($pid == 0){ //这里写我们的逻辑

foreach($master[$slice] as $val)

{ //这里发生短信

echo sprintf(\"大众%s Child:%s \r\n\"大众,$slice,$val);

} //子进程实行完之后务必需要关闭;

exit();

}else

{ //程序发生缺点也须要关闭程序

exit();

}

$slice--;

} // 等待所有子进程结束后回收资源

while(!empty($childList)){

$childPid = pcntl_wait($status); if ($childPid > 0){ unset($childList[$childPid]);

}

}

}/ 运行的结果如下,phone不是连续的

Slice id:19,phone:66558

Slice id:23,phone:79921

Slice id:19,phone:66559

Slice id:23,phone:79922

Slice id:19,phone:66560

Slice id:23,phone:79923

Slice id:19,phone:66561

Slice id:23,phone:79924

Slice id:19,phone:66562

Slice id:23,phone:79925

/

通过pcntl扩展,几句代码就利用多进程将发关照的功能提速了30倍。
不过这么大略的多进程编码,我为什么会在文章开始形容的如此繁芜呢?

重点和难点还是进程间通信,由于我们给用户发短信的每个子进程是相对独立的,进程之间没有通信,不会相互通报数据状态。
以是不会发生资源抢占与锁问题。
如果需求发生变革,我们须要按用户的生动度高低给用户发短信,该怎么做?

普通点阐明如下:一个盘子里有30个苹果,须要发给30个人,由3个人卖力发苹果。
最大略的办法便是我们先把苹果分成3份,3个人一人一份,很快就能发完。
但是如果我们要按照苹果的大小顺序去发,把大苹果先发出去,此时我们就没办法分成3份了,只能三个人相互去挣当前最大的,很随意马虎就打起来。
那该怎么做呢?最常见的办法便是利用一个工具把所有苹果按由大到下的顺序放在里面,每次只能取一个,这样就办理了资源抢占的问题。

关于进程间资源抢占的问题非常的繁芜,编码难度非常高,这也是为什么很少利用PHP跑多进程的缘故原由。
当须要用到多进程时我们更乐意去利用Python或者Java,它们对多线程封装的更好。
须要重点说的是PHP并不是不能写多进程的程序,也不是像其他人说的不稳定,而是编码费时,掩护本钱高。

二. 进程间通信

常见的进程通信办法有:行列步队、共享内存与旗子暗记量、管道、socket,我将逐一举例解释。

行列步队

『行列步队』是在的传输过程中保存的容器。
行列步队管理器相称于发送者和吸收者的中介。
行列步队的紧张目的是创建路由并且担保可靠通报;如果发送时吸收者不可用,行列步队会保留,直到有人吸收它。

行列步队可供应临时存储的功能并且能担保可靠的通报,我们恰好利用它实现进程间通信。
当然行列步队不单单用于进程间通信,他的运用领域非常广。
比如行列步队非常适用于办理消费者和生产者的问题,由于生产者和消费者之间总会存在『速率差』。
比如生产者溘然少了10个,两边处理的速率就会不平衡,会导致排队壅塞,做事不可用。
这肯定不是我们想看到的,如果这时候引入行列步队将两个别系解耦,无论谁慢了都不会影响整体业务。

function demo(array $phoneList){ global $msgQueue;

$cnt = count($phoneList); //测试数组大小

$slice = 3; //须要调用的进程数量

$childList = []; //主进程先发送一条,见告子进程可以发送第一条短信了

msg_send($msgQueue,MSG_TYPE,0); while($slice >= 0)

{

$pid = pcntl_fork(); if($pid > 0){

$childList[$pid] = 1; //父进程什么都不用做

}elseif($pid == 0){ //子进程一直的要求,直到所有短信发送完成

while(msg_receive($msgQueue,MSG_TYPE,$msgType,1024,$message))

{ if($cnt>intval($message))

{

printf(\"大众Slice id:%s,phone:%s \r\n\公众,$slice,$phoneList[$message]);

$message = $message + 1;

msg_send($msgQueue,MSG_TYPE,$message);

}else

{ //关照其他进程统统都结束了

msg_send($msgQueue,MSG_TYPE,$cnt); exit();

}

}

}else

{ //程序发生缺点也须要关闭程序

exit();

}

$slice--;

} // 等待所有子进程结束后回收资源

while(!empty($childList)){

$childPid = pcntl_wait($status); if ($childPid > 0){ unset($childList[$childPid]);

}

}

}const MSG_TYPE = 1;//创建行列步队$id = ftok(__FILE__,'m');

$msgQueue = msg_get_queue($id);

demo(range(0,900));/运行结果,按大小输出

Slice id:1,phone:895

Slice id:1,phone:896

Slice id:2,phone:897

Slice id:3,phone:898

Slice id:3,phone:899

/

共享内存与旗子暗记量

『共享内存』很随意马虎理解,便是在内存中找一块区域,所有进程都能读写。
『旗子暗记量』是系统供应的一种原子操作,进程在开启旗子暗记和结束旗子暗记之间拥有共享内存的『绝对霸占』权,这样能有效的防止多个进程读取同一个资源时发生去世锁。

function demo(array $phoneList){ global $shareMemory; global $signal;

$cnt = count($phoneList); //测试数组大小

$slice = 3; //须要调用的进程数量

$childList = []; while($slice >= 0)

{

$pid = pcntl_fork(); if($pid > 0){

$childList[$pid] = 1; //父进程什么都不用做

}elseif($pid == 0){ while(true)

{ // 标记旗子暗记量,这里被我承包了

sem_acquire($signal); //检测共享内存是否存在

if (shm_has_var($shareMemory,SHARE_KEY)){ //从共享内存中拿数据

$val = shm_get_var($shareMemory,SHARE_KEY); if($val>=$cnt)

{

sem_release($signal); break;

}else

{

printf(\"大众Slice id:%s,phone:%s \r\n\"大众,$slice,$phoneList[$val]);

$val ++; //再将数据写入共享内存

shm_put_var($shareMemory,SHARE_KEY,$val);

}

}else{ // 无值会,先初始化

shm_put_var($shareMemory,SHARE_KEY,0);

} // 用完开释

sem_release($signal);

} exit();

}else

{ //程序发生缺点也须要关闭程序

exit();

}

$slice--;

} // 等待所有子进程结束后回收资源

while(!empty($childList)){

$childPid = pcntl_wait($status); if ($childPid > 0){ unset($childList[$childPid]);

}

}

}const SHARE_KEY = 1;// 创建一块共享内存$shm_id = ftok(__FILE__,'a');

$shareMemory = shm_attach($shm_id);// 创建一个旗子暗记量$sem_id = ftok(__FILE__,'b');

$signal = sem_get($sem_id);

demo(range(0,900));// 开释共享内存与旗子暗记量shm_remove($shareMemory);

sem_remove($signal);/运行结果,按大小输出

Slice id:1,phone:775

Slice id:3,phone:776

Slice id:3,phone:777

Slice id:3,phone:778

Slice id:0,phone:779

Slice id:0,phone:780

/

管道

管道是比较常用的进程间通信手段,管道又分为匿名管道(pipe)与具名管道(mkfifo),匿名管道只能用于具有亲缘关系的进程间通信,而具名管道可以用于同一主机上任意进程。

pipe与mkfifo的紧张差别是mkfifo会创建一个分外的FIFO物理文件,这个FIFO文件其他进程都可以像读写一样平常文件一样读写。
再写下去文章就太长了,之后写下一篇吧。

未完待续……

PS:所有代码都放到了GitHub:php_thread_demo

沟通和互动以及更多干货,欢迎关注新浪微博:@阿里如斯栖社区

标签:

相关文章

GCCC语言,构建高效编程世界的基石

C语言作为一种历史悠久的编程语言,以其简洁、高效和可移植性等特点,在计算机科学领域占据着举足轻重的地位。GCC(GNU Compi...

PHP教程 2024-12-26 阅读0 评论0

青岛与济南,双城IT产业的协同发展之路

随着我国经济的持续增长,信息技术产业在国民经济中的地位日益凸显。青岛和济南作为山东省内两大重要城市,近年来在IT产业方面取得了显著...

PHP教程 2024-12-26 阅读0 评论0

E语言读网页,技术革新下的信息获取新途径

随着互联网的普及,人们获取信息的方式发生了翻天覆地的变化。从传统的报纸、杂志到如今的网络新闻、社交媒体,信息传播的速度和广度都得到...

PHP教程 2024-12-26 阅读0 评论0

风趣原野,探索自然之美,品味生活之趣

“原野,是自然的舞台,是生命的摇篮。在这片广袤的土地上,风趣原野,以其独特的魅力,吸引着无数人前来探索、品味。”这是著名作家鲁迅先...

PHP教程 2024-12-26 阅读0 评论0

DNF调语言,探索数字货币的全新领域

随着互联网技术的飞速发展,数字货币作为一种新兴的金融工具,逐渐受到人们的关注。在众多数字货币中,DNF(DogeCoin)凭借其独...

PHP教程 2024-12-26 阅读0 评论0

D语言,未来编程的璀璨新星

在数字化时代,编程语言层出不穷,其中D语言以其独特的优势脱颖而出,成为编程领域的一颗璀璨新星。本文将从D语言的特点、优势以及应用领...

PHP教程 2024-12-26 阅读0 评论0