SWOOLE PROCESS多进程模型

news/2025/11/13 15:44:22/文章来源:https://www.cnblogs.com/sblack/p/19218289
<?php
class SwooleProcessController {//主进程pidprotected $pidfile = "";//构造函数public function __construct(){$this->pidfile = LOG_PATH."swoole/consumer_master.pid";}//初始化一些参数public function start(){//命令$cmd = $_SERVER['argv'][2] ?? "start";//woker数量$workernum = $_SERVER['argv'][3] ?? 1;//daemon$daemon = in_array('-d',$_SERVER['argv'],true);//基于命令switch($cmd){case "start":$this->startmain($daemon,$workernum);break;case "stop":$this->stop();break;case "status":$this->status();break;default:echo "wrong cmd";exit(1);}}/*** 启动进程* @param int $daemon 是否守护* @param int $workernum worker数量*/public function startmain($daemon,$workernum){if($this->is_running()){echo "Already running.PID=".trim(file_get_contents($this->pidfile)) . PHP_EOL;return;}//守护进程if($daemon){\Swoole\Process::daemon(true,true);}//leaderposix_setsid();//主进程ID$masterpid = posix_getpid();file_put_contents($this->pidfile,(string)$masterpid);//设置主进程名称swoole_set_process_name("php:consumer master");$running = true;$workers = [];//设置异步信号监听pcntl_async_signals(true);pcntl_signal(SIGTERM,function() use (&$running,&$workers){debugLog("Master recv SIGTERM, worker count=".count($workers), 'swoole/consumer.log');$running = false;\Swoole\Timer::clearAll();foreach($workers as $pid=>$_){debugLog("kill child pid: {$pid}",'swoole/consumer.log');\Swoole\Process::kill($pid,SIGTERM);}});pcntl_signal(SIGINT, function() use (&$running, &$workers) {$running = false;foreach ($workers as $pid => $_) {\Swoole\Process::kill($pid, SIGTERM);}});//\Swoole\Timer::tick(1000, function(){});//\Swoole\Event::wait(); //启动子进程workerfor($i=0;$i<$workernum;$i++){$this->startworker($workers,$i);}//处理子进程异常退出\Swoole\Process::signal(SIGCHLD,function() use (&$workers,&$running){while($ret = \Swoole\Process::wait(false)){$pid = $ret['pid'];$code = $ret['code'];$sig = $ret['signal'];unset($workers[$pid]);if($running){$id = $ret['pid'] % 10000;$this->startworker($workers,$id);}}});//主进程事件循环while($running){pcntl_signal_dispatch();sleep(1);}//等待子进程退出$waitStart = time();while(!empty($workers) && time() - $waitStart < 10){sleep(1);}@unlink($this->pidfile);debugLog("Master Stoppd.","swoole/consumer.log");}/*** 记动一个子进程*/public function startworker(&$workers,$workerid):void{$process = new \Swoole\Process(function(\Swoole\Process $proc) use ($workerid){swoole_set_process_name("php:consumer worker#{$workerid}");//worker主进程$this->workerMain($workerid);},false,0,true);$pid = $process->start();$workers[$pid] = $process;debugLog("Worker started. id={$workerid}, pid={$pid}\r\n",'swoole/consumer.log');}/*** worker 主进程*/public function workerMain($workerid){$running = true;pcntl_async_signals(true);$objredis = Apps::redis('cms');\Swoole\Process::signal(SIGTERM, function() use (&$running, $objredis) {$running = false;$objredis->close(); // 立即唤醒 brPop});\Swoole\Process::signal(SIGINT, function() use (&$running, $objredis) {$running = false;$objredis->close();});while($running){try {$result = $objredis->brPop('testswoolekey', 5);if(empty($result)){continue;}debugLog($result[1], 'swoole/data.log');} catch (\Exception $e) {if (!$running) break;usleep(20000);}}debugLog("Worker {$workerid} exited", 'swoole/consumer.log');}//停止public function stop(){if(!$this->is_running()){echo "Not running";return ;}$pid = (int)trim(file_get_contents($this->pidfile));$pgid = posix_getpgid($pid);if($pgid > 0){echo "Stop signal sent to PGID={$pgid}\r\n";posix_kill(-$pgid,SIGTERM);} else {posix_kill($pid,SIGTERM);	echo "Stop signal sent to master PID={$pid}\r\n";}//等待退出$timeout = 10;while($timeout-- > 0){if($pgid > 0){if(!posix_kill($pid,0)) break;} else {if (!posix_kill($pid, 0)) break;}sleep(1);}if($pgid > 0){posix_kill(-$pgid, SIGKILL);echo "Force killing PGID={$pgid}\n";} else {\Swoole\Process::kill($pid,SIGKILL);echo "Force killing master PID={$pid}\r\n";	}@unlink($this->pidfile);}public function stop2(){if (!$this->is_running()) {echo "Not running\n";return;}$pid = (int)trim(@file_get_contents($this->pidfile));if ($pid <= 0) {echo "Invalid PID file\n";return;}$pgid = @posix_getpgid($pid);if ($pgid > 0) {echo "Sending SIGTERM to process group PGID={$pgid}\n";posix_kill(-$pgid, SIGTERM);} else {echo "Sending SIGTERM to master PID={$pid}\n";posix_kill($pid, SIGTERM);}// 等待进程优雅退出$timeout = 10;$graceful = false;while ($timeout-- > 0) {if (!posix_kill($pid, 0)) {$graceful = true;break;}echo "Waiting for process to exit... ({$timeout}s left)\n";sleep(1);}// 检查是否仍在运行if (!$graceful) {echo "Process did not exit in time, sending SIGKILL...\n";if ($pgid > 0) {posix_kill(-$pgid, SIGKILL);} else {posix_kill($pid, SIGKILL);}// 再次确认是否真的被杀掉sleep(1);if (posix_kill($pid, 0)) {echo "Warning: process still alive after SIGKILL!\n";} else {echo "Process group successfully killed.\n";}} else {echo "Process exited gracefully.\n";}// 最后安全删除 pid 文件if (file_exists($this->pidfile)) {@unlink($this->pidfile);}}//状态public function status(){if(!$this->is_running()){echo "not running";return;}$pid = (int)trim(file_get_contents($this->pidfile));echo "Running:Master PID={$pid}";}public function is_running():bool {if(!is_file($this->pidfile)) return false;$pid = (int)trim(@file_get_contents($this->pidfile));return $pid>0 && posix_kill($pid,0);}}

基本实现进程启动,停止,进程数量,状态,主进程子进程信号监听

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/964402.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【备忘】通用查询增加一个与查询实体不相关的简单条件方法

【备忘】通用查询增加一个与查询实体不相关的简单条件方法譬如查询病历文书及其相关操作日志,明细DtoStrucDoc,DtoEncounter里的信息都是具有查询意义的,但是如果想增加一个“是否出院记录”的查询条件,就不知道往…

如何 运行 seatunnel web 开发版

如何 运行 seatunnel web 开发版1.概述 seatunnel 是一个实现数据库同步的执行引擎,但是他需要用户自己编写 同步定义文件。如果是一次执行需要使用命令执行同步,如果是集群部署,需要用户提交同步定义文件. seatunn…

苏珊大爷

better-wubi是一个 86 版五笔输入法的改进版码表。我看到了:agdw 苏珊大爷 “苏珊大爷”是2010年中国大陆选秀节目《快乐男声》中因年龄、外貌与才艺反差引发关注的大龄男性参赛者的代称,源自英国“苏珊大妈”现象,…

深入解析:mysql_page pagesize 如何实现游标分页?

深入解析:mysql_page pagesize 如何实现游标分页?2025-11-13 15:38 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; disp…

Continuous Trajectory: 从 Independent Set Process 到另类 Giant Component

Independent Set Process 大部分时候,随着一个自然的随机过程的进行,随机变量的变化都很平滑。例如,考虑在 \(G(n,p)\) 上进行如下的贪心求最大独立集算法:从 1 到 \(n\) 遍历每个点,能选就选。这里我们假设 \(p=…

c++初学者的随笔记录_1

include include---->> system("pause");有此头文件才能写这个代码。功能:让一闪而过的windows控制面板持久出现 using namespace std--->>如果没有这个 std 命名空间则需要std:: 这样来写。…

Bakas Trick

Trick 名何意味。 又名:不删除双指针。 常用于数区间,区间信息通常带有可合并的特质,也就是通常可以用线段树维护,如区间加,区间上的动态 DP(矩阵乘法)。 实现方法是:定义双指针 \(L,R\) 与辅助变量 \(\mathrm…

bug等级

1级bug (致命bug) 1级:立即处理 2级bug(严重bug) 2级:紧急处理 3级bug (一般bug) 3级:正常处理 4级bug(建议性bug) 4级:有时间处理

从0到1构建一个稳定redis架构

从0到1搭建一个稳定的redis集群 1、单机版redis单机版的redis就是业务系统把他用作缓存使用,从mysql中查询数据然后写入到redis中,后面再查询的时候就会优先查询缓存。因为redis运行在内存中,所以速度很快。若业务体…

WireWorld 美国线世界:以专利科技重塑家用音响线缆的高保真革命

本文聚焦美国 WireWorld 线世界音响线缆,阐述其以 Cable Comparator 测试系统、DNA Helix 等专利技术为核心,凭借优质导体与绝缘材料,打造覆盖全场景的高保真产品矩阵。在音响发烧友的世界里,线缆被喻为 “音质的最…

bug的内容包含(重点)

所属产品、所属模块、所属项目、影响版本、操作系统、浏览器、当前指派、 bug类型、bug标题、重现步骤、相关需求、严重程度、优先级

从淘宝推荐到微信搜索:查找算法如何支撑亿级用户——动画可视化 - 教程

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

JVM系列——垃圾收集(1)

https://tech.meituan.com/2020/08/06/new-zgc-practice-in-meituan.htmlhttps://www.bilibili.com/video/BV1US4y1m7if/?spm_id_from=333.337.search-card.all.click&vd_source=99ec55b57f4eeedd9ed62c43e87cb6f…

2025年上海统招专升本平台权威推荐榜单:上海专升本/上海全日制专升/上海专升本培训平台精选

在学历提升需求持续增长的背景下,上海统招专升本已成为专科生获得本科学历的重要途径,选择优质的教育服务平台对考生备考至关重要。 近年来,上海地区统招专升本报考人数呈现稳步增长趋势。据教育统计数据显示,2024…

bug的类型

代码错误、界面优化、设计缺陷、配置相关、安装部署、性能问题、标准规范、测试脚本等

Codeforces 1120D Power Tree 题解 [ 蓝 ] [ 树形 DP ] [ 记忆化搜索 ] [ 图论建模 ] [ 最小生成树 ] [ 差分 ]

Power Tree 简单题,场上大概写了 50min。 Sol.1 树形 DP 对所有数变 \(0\) 的条件进行刻画,把子树的条件画在序列上。具体而言,我们求出树的中序遍历,选择一个节点等价于将其子树的区间 \([l, r]\) 分离出来,即在…

软件开发公司的隐形资产:为什么设计思维比代码量更值钱?

软件开发公司的隐形资产:为什么设计思维比代码量更值钱?代码量陷阱:软件开发的认知误区 在软件开发行业,“代码量”曾长期被当作衡量开发能力与项目价值的硬指标。不少企业将日均代码行数、功能模块数量作为考核标…

mybatis 打印执行SQL

import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; import com.baomidou.mybatisplus.extension.plugins.inner.DynamicTableNameInnerInterceptor; import lombok.extern.slf4j.Slf4j; imp…

10年湛江老导游私藏路线!除了生蚝,这座海滨之城还有多少惊喜等你发现

各位旅友,大家好! 我是导游小胡,在湛江这座美丽的海滨城市已经做了整整10年导游。今天,我想带大家看看,除了远近闻名的湛江生蚝,这座城市还有哪些让人流连忘返的风景。 湖光岩:世界地质奇观的秘密 作为世界第二…

ld.lld: error: undefined symbol: _impure_ptr 出现该问题解决办法

ld.lld: error: undefined symbol: _impure_ptr 出现该问题解决办法 解决方案命令 方法1:显式链接newlib gcc -specs=nosys.specs your_source.c -o output方法2:使用完整newlib gcc --specs=rdimon.specs -lrdimon …