首页 » SEO优化 » phpworker技巧_看看 PHP 高机能框架 Workerman 源码中旗子暗记的运用姿势

phpworker技巧_看看 PHP 高机能框架 Workerman 源码中旗子暗记的运用姿势

访客 2024-10-23 0

扫一扫用手机浏览

文章目录 [+]

旗子暗记是一种轻量级通报机制,常日用于软件中断的异步关照。
比如我们常用的kill -9 xxx便是向xxx程序发送旗子暗记,逼迫终止其进程。
还有我们常常利用的Ctrl+C或者Ctrl+D等键盘操作事宜,也会产生终端退出旗子暗记。

然而,旗子暗记在我们日常的业务编程中却很少涉及。
这是由于旗子暗记常日用于进程管理,例如父子进程之间的通信、进程资源的管理等,因此PHP-FPM模式下不会利用多进程编程。
如果那位大胆的朋友利用了,恭喜你,你会得到意想不到的惊喜。

phpworker技巧_看看 PHP 高机能框架 Workerman 源码中旗子暗记的运用姿势

不过,如果你是常常利用或编程的朋友,你该当对旗子暗记有很好的理解。
不管你是否打仗过旗子暗记,都建议你学习一下它的事理和用法,大概对往后的编程会有帮助。
毕竟,技能只是须要韶光的东西。
为了更随意马虎地描述该旗子暗记,我将用一个口语例子来阐明它。
假设您是一名工薪阶层。
这里彷佛没有必要假设,由于你是工薪阶层。
哈哈,此时你戴着耳机,沉浸在代码的天下里。

phpworker技巧_看看 PHP 高机能框架 Workerman 源码中旗子暗记的运用姿势
(图片来自网络侵删)

溘然公司收音机里响起了吃“下午茶”的音乐,你赶紧跑到下午茶桌前准备。
刚吃完鸡腿,公司广播又响起了网络bug警告。
你只好把鸡腿含在嘴里,回到座位上办理问题。
网上的问题还没有办理。
这是公司广播关照你参加某次答辩会议,但这次你没有韶光去关注这个关照,以是你完备忽略了它。

你可以将这里的公司理解为操作系统,将广播关照理解为旗子暗记,将自己理解为进程。
收到旗子暗记后就可以做相应的事情,也可以做与关照无关的事情。
比如,关照见告你改正一个线上bug,但你舍不得下午茶,想连续吃,那么你也可以任性,不及时改正。
“只是事后会被批评,哈哈。

或者,您可以忽略该关照并完备忽略它。
这句话虽然说得好听,但中国有句古话:“说得好,不如做得好”。
那么接下来我们就通过实际例子来深入代码。

下面是当提高程吸收外部旗子暗记的例子。
利用回调函数注册指定的旗子暗记,回调函数会根据吸收到的不同旗子暗记进入相应的分支实行相应的处理逻辑。

处理完毕后,即可退出程序。
个中h函数起到的浸染是监听要处理的旗子暗记,并实行该旗子暗记注册的回调函数。
而where(true)会连续循环,直到吸收到旗子暗记。

复制

<?php// 定义旗子暗记处理函数function signalHandler($signal){ switch ($signal) { case SIGINT: // 比如公司广播响起了吃 下午茶 的音乐 echo "捕获到 SIGINT 旗子暗记... " . PHP_EOL; // 接下来可以自行实现相应的逻辑 exit; case SIGTERM: // 比如公司广播又响起了线上 Bug 的告警声 echo "捕获到 SIGTER 旗子暗记... " . PHP_EOL; // 接下来可以自行实现相应的逻辑 exit; case SIGALRM: // 比如公司广播又关照你参加某某答辩会 echo "捕获到 SIGALRM 旗子暗记... " . PHP_EOL; // 接下来可以自行实现相应的逻辑 // 当然你也可以不处理,任由它去 exit; default: echo "捕获到未知旗子暗记: $signal " . PHP_EOL; exit; }}// 注册旗子暗记回调函数// 就好比接管到不同的关照,就该当要做对应的事情// 这里统一回调 signalHandler 这个函数,你也可以定义不同的函数pcntl_signal(SIGINT, 'signalHandler');pcntl_signal(SIGTERM, 'signalHandler');// 输出一下当前的进程号,方便测试echo "当提高程 PID: " . getmypid() . PHP_EOL;// 不断监听旗子暗记,吸收到旗子暗记后调用相应的旗子暗记回调函数// 这里就像你自己的耳朵一贯在等待吸收关照while (true) { pcntl_signal_dispatch();}1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.27.28.29.30.31.32.33.34.35.36.37.38.39.40.41.42.

实行php index.php命令启动程序,然后通过kill向进程发送旗子暗记。
该旗子暗记终极将在回调函数中被捕获。

复制

[manongsen@root php_signal]$ php index.php 当提高程 PID: 43195[manongsen@root php_signal]$ kill -SIGTERM 43195[manongsen@root php_signal]$ php index.php 当提高程 PID: 43195捕获到 SIGTERM 旗子暗记...1.2.3.4.5.6.7.8.

我们来看一个进程间旗子暗记传输的例子。
假设你因当前公司的内部摩擦而被杀,然后你开始探求替代者。
末了,你找到了一个滚王,但事情了一段韶光后,他就跑了。
末了,你我无奈,只能逃跑。

创建子进程,父进程调用函数注册旗子暗记的回调函数,父进程不断监听该旗子暗记。
直到子进程退出,父进程终于触发回调函数,开始回收子进程的资源,然后父进程也退出。

复制

<?php// 定义旗子暗记处理函数function signalHandler($signal){ $pid = getmypid(); // 回收子进程资源 // 你吸收到了他跑路的旗子暗记,开始回收他的代码权限、账号等资源 $status = 0; $cid = pcntl_wait($status, \WUNTRACED); echo "父进程: {$pid}, 收到子进程: {$cid}, 退出旗子暗记: {$signal}" . PHP_EOL; // 末了你抵不住也跑路了 echo "父进程: {$pid}, 末了也退出了" . PHP_EOL; exit;}// 在当提高程 Fork 一个子进程// 比如终于招聘了一个替补你的人$pid = pcntl_fork();if ( $pid < 0 ) { // 这里被你放鸽子了 // 你也摆烂直接跑路算了 exit('fork error');} else if( $pid > 0 ) { // 父进程实行空间 ... echo "父进程: " . getmypid() . PHP_EOL; // 注册旗子暗记回调函数 // SIGCHLD 表示一个子进程已经终止或停滞 // 你相称于给他触发跑路的旗子暗记,准备了一个处理方案 pcntl_signal(SIGCHLD, "signalHandler"); // 监听旗子暗记 // 你相称于一贯监听他的动向 while(true){ pcntl_signal_dispatch(); }} // 子进程实行空间 ...$cid = getmypid();echo "子进程: {$cid}" . PHP_EOL;// 休眠 5 秒钟sleep(5);// 退出// 假设他干了5秒钟就跑路了exit;1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.27.28.29.30.31.32.33.34.35.36.37.38.39.40.41.42.43.44.45.46.47.48.49.50.

实行.php即可看到对应的实行结果。

复制

[manongsen@root php_signal]$ php index.php 父进程: 47008子进程: 47009子进程: 47009 退出了父进程: 47008, 收到子进程: 47009, 退出旗子暗记: 20父进程: 47008, 末了也退出了1.2.3.4.5.6.

有了上面两个例子的根本,我们再看源码中旗子暗记的利用就会更加得心应手。
打开 .php 文件中的第 548 行。
该函数会调用函数注册旗子暗记回调函数,同时也会调用函数监听来自子进程的旗子暗记。

复制

<?php// workerman/Worker.php:548public static function runAll(){ // ... // 注册旗子暗记回调函数 static::installSignal(); // ... // 监听 Worker 子进程旗子暗记 static::monitorWorkers();}1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.

看到这个函数的实现,是不是有一种似曾相识的觉得?与上例中的注册方法基本相同。

复制

<?php// workerman/Worker.php:1140protected static function installSignal(){ // ... // 旗子暗记回调函数 $signalHandler = '\Workerman\Worker::signalHandler'; // 退出旗子暗记 \pcntl_signal(\SIGINT, $signalHandler, false); \pcntl_signal(\SIGTERM, $signalHandler, false); \pcntl_signal(\SIGHUP, $signalHandler, false); \pcntl_signal(\SIGTSTP, $signalHandler, false); // 优雅退出旗子暗记 \pcntl_signal(\SIGQUIT, $signalHandler, false); // 重载旗子暗记 \pcntl_signal(\SIGUSR1, $signalHandler, false); // 优雅重载旗子暗记 \pcntl_signal(\SIGUSR2, $signalHandler, false); // 状态旗子暗记 \pcntl_signal(\SIGIOT, $signalHandler, false); // 连接状态旗子暗记 \pcntl_signal(\SIGIO, $signalHandler, false); // SIGPIPE 管道旗子暗记,忽略该旗子暗记 \pcntl_signal(\SIGPIPE, \SIG_IGN, false);}1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.

该函数吸收来自子进程的旗子暗记,并根据不同的旗子暗记分支到不同的情形。

复制

<?php// workerman/Worker.php:1220public static function signalHandler($signal){ switch ($signal) { // 退出 case \SIGINT: case \SIGTERM: case \SIGHUP: case \SIGTSTP: static::$_gracefulStop = false; // 这里会把所有的 Woker 子进程 Kill 掉,并且销毁相应子进程的 Event-Loop 事宜循环 static::stopAll(); break; // 优雅的退出 case \SIGQUIT: // 优雅退出在调用 posix_kill 函数时通报的是 SIGTERM 旗子暗记 static::$_gracefulStop = true; static::stopAll(); break; // 重载 case \SIGUSR2: case \SIGUSR1: if (static::$_status === static::STATUS_SHUTDOWN || static::$_status === static::STATUS_RELOADING) { return; } static::$_gracefulStop = $signal === \SIGUSR2; static::$_pidsToRestart = static::getAllWorkerPids(); // 对 Worker 进程实现重载 static::reload(); break; // 展现状态 case \SIGIOT: // 这里会输出一些 全局状态信息、进程状态信息 // 比如 load-average、event-loop、workers-count 等 static::writeStatisticsToStatusFile(); break; // 展现连接状态 case \SIGIO: // 这里会输出一些进程连接干系的统计信息 // 比如 Recv-Q、Send-Q、Bytes-R、Bytes-W、Status 等 static::writeConnectionsStatisticsToStatusFile(); break; }}1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.27.28.29.30.31.32.33.34.35.36.37.38.39.40.41.42.43.44.45.46.

末了启动监听函数ux。
除了监听旗子暗记之外,它还做一些资源回收事情。
其余,还回调了用户自定义的Stop函数,方便一些业务处理。

复制

<?php// workerman/Worker.php:1735protected static function monitorWorkersForLinux(){ // 默认运行状态 static::$_status = static::STATUS_RUNNING; // 一贯监听直到所有的进程退出 while (1) { \pcntl_signal_dispatch(); $status = 0; // 这些做一些子进程资源的回收事情 $pid = \pcntl_wait($status, \WUNTRACED); \pcntl_signal_dispatch(); // ... // 做一些清理事情 if (static::$_status === static::STATUS_SHUTDOWN && !static::getAllWorkerPids()) { // 这里还会回调用户设定的 Stop 回调函数,便于做一些业务上的处理 // 然后直接 exit 当提高程 static::exitAndClearAll(); } }}1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.

旗子暗记最常用于涉及多进程编程的场景。
例如,在主进程中,通过旗子暗记来监控子进程的状态,可以及时获取子进程的运行信息。
一旦子进程挂起,可以快速规复。
,全体做事进程退出后可以及时回收内存资源。

其余,在Linux系统下,我们常常利用Kill命令向进程通报旗子暗记,但大多数情形下它是用来逼迫结束进程的。
这是终止进程的最大略、最粗暴的方法。
不过我以前也碰着过某些病毒进程无论如何也杀不掉。
我想知道以前有人见过这个吗?

这次紧张分享了旗子暗记的一些根本知识,以及源码中的利用姿势。
您最好练习一下本文中的这些示例。
经由练习,相信你会对旗子暗记有更深入的理解。
希望能够对大家有所帮助。
帮助。

鱼云专注于供应高性能云做事器和物理做事器租赁做事。
我们致力于为企业供应安全、稳定、高效的办理方案,确保数据无忧、业务顺畅。

标签:

相关文章

我国土地利用分类代码的构建与应用

土地利用分类代码是我国土地管理的重要组成部分,是土地资源调查、规划、利用和保护的依据。土地利用分类代码的构建与应用显得尤为重要。本...

SEO优化 2025-02-18 阅读1 评论0

微信跳转微信支付便捷支付体验的秘密武器

移动支付已成为人们日常生活中不可或缺的一部分。作为我国领先的社交平台,微信支付凭借其便捷、安全的支付方式,深受广大用户的喜爱。而微...

SEO优化 2025-02-18 阅读1 评论0

探寻会计科目代码背后的奥秘分类与

会计科目代码是会计信息系统中不可或缺的组成部分,它将企业的经济活动进行分类和归纳,为会计核算、财务分析和决策提供重要依据。本文将从...

SEO优化 2025-02-18 阅读1 评论0