首页
下载
文档
问答社区
视频
捐赠
源代码
AI 助理
赞助商
CRMEB
Apipost
腾讯云
微擎
禅道
51Talk
商业产品
Swoole AI 智能文档翻译器
Swoole-Compiler PHP 代码加密器
CRMEB 新零售社交电商系统
登录
注册
全部
提问
分享
讨论
建议
公告
开发框架
CodeGalaxy
发表新帖
Swoole\Process\Pool 产生大量 TIME_WAIT 进程
### 问题描述 Swoole\Process\Pool 产生大量 TIME_WAIT 进程,不超过400个 一直在 400以下波动,一启动,就从0增加到 390,然后一直波动400以下 目前初学。各位大佬勿怪 ### Swoole版本,PHP版本,以及操作系统版本信息 PHP7.4.8 swoole 4.7.1 ### 相关代码 ```php <?php error_reporting(E_ALL); ini_set("display_errors","On"); ini_set('date.timezone','Asia/Shanghai'); //$a = [ // ['id'=>7], // ['id'=>17], // ['id'=>27], // ['id'=>37], // ['id'=>47], //]; //echo json_encode($a);exit; //$redis = getRedis(); //$A = $redis->lPop('aaa'); //print_r($A);exit; function getAll($sql) { $mysql = new mysqli('10.28.41.244','huangchunlong','47M$FQa3#GeWqfX#m8ssiCui!4KQ34fg','test'); if(!$mysql) exit("connect error:".mysqli_connect_error()); $rs = $mysql->query($sql); $c = array(); while($r = $rs->fetch_assoc()){ $c[] = $r; } $mysql->close(); return $c; } function getRedis() { $redis = new Redis(); $redis->connect("10.28.41.244", 7000); //pconnect连接 $redis->auth("fxrXQ%gL%Kh7Hz42"); return $redis; } function getRow($sql) { $mysql = new mysqli('10.28.41.244','huangchunlong','47M$FQa3#GeWqfX#m8ssiCui!4KQ34fg','test'); if(!$mysql) exit("connect error:".mysqli_connect_error()); $rs = $mysql->query($sql); $row = $rs->fetch_assoc(); $mysql->close(); return $row; } //记录日志 单元测试用 $content 日志内容 $file日志名称 保存在public/runtime/logic目录下 function logs($content, $file='logic.log') { $now = date('Y-m-d H:i:s'); $content = "[{$now}]: {$content}\r\n"; $path = '/runtime/'; $file = $path.$file; if(!is_dir($path)) mkdir($path,0777,true); error_log($content,3,$file); } //需要处理的计划任务,可以是Redis队列或者其他 //redis 长久连接。需要在底层用发 比如POP 等加try catech 判断错误异常原因,然后重新连接,在去执行方法 /* 1.开启2个进程,一个就是这个进程,另外一个就是检测进程,检测配置的更新时间是否更新。更新后发送信号给POLL进程池 2.he和监控程序一起加入supvisor里面 * */ //获取当前主进程ID,写入文档或者redis $redis = getRedis(); $kes = 'redis_masterpid_key'; $redis->set($kes, getmypid()); $workerNum = 3; $pool = new Swoole\Process\Pool($workerNum); $pool->set([ 'max_wait_time' => 60, 'reload_async' => true, ]); cli_set_process_title('mqlistenkey'); $pool->on("WorkerStart", function ($pool, $workerId) use($workerNum) { //开启定时器 if($workerId == 0) { echo "wsohis0000000000000000\n\n"; } echo "Worker#{$workerId} ".getmypid()." is started\n"; $process = $pool->getProcess(); // //工作进程为异步模式,请使用 Swoole\Process::signal 监听信号 //工作进程为同步模式,请使用 pcntl_signal 和 pcntl_signal_dispatch 监听信号 pcntl_signal(SIGTERM, function ($sign) use ($process,$workerId) { logs("进程ID:".$workerId.",监听到信号$sign ,终止"); $process->exit(); }); //// $process->exec('/opt/extend/php74/bin/php', ['-r', 'var_dump(swoole_version());']); //执行这个下面不执行 /// $childProcess->exec('/usr/local/bin/php', ['/var/www/project/yii-best-practice/cli/yii', 't/index', '-m=123', 'abc', 'xyz']); // exec 系统调用 // print_r($process->pid); /** Swoole\Process Object ( [pipe] => [msgQueueId] => [msgQueueKey] => [pid] => 16968 [id] => 1 [callback:Swoole\Process:private] => ) */ // if($workerId !=0) { // // } else { // // } $redis = getRedis(); $arr = getAll("select * from mq where id%$workerNum=$workerId and status=0"); $key = "hash_redis_".$workerId; $max = []; foreach ($arr as $v) { $max[] = $v['u_t']; $v['time'] = date('Y-d-d H:i:s'); $redis->hSet($key,$v['id'],json_encode($v)); //这里请求外部接口。。。执行一系列操作。或者是去获取Redis配置 } sleep(1); if(!empty($max)) { $lastut = max($max); } else { $lastut = 0; } logs("进程ID:".$workerId.",当前最大UT:".$lastut); pcntl_signal_dispatch(); // try { //// Swoole\Timer::tick(2000, function($timer_id,$lastut,$workerNum,$workerId,$pool){ //// logs("进程ID:".$workerId.",进入定时器-----------------"); //// $last = getRow("select u_t from mq where id%$workerNum=$workerId and status=0 order by u_t desc limit 1"); //// logs("进程ID:".$workerId.",定时器查询最大UT:".$last); //// if($last['u_t'] > $lastut && $lastut != 0) { //// logs("进程ID:".$workerId.",进程杀掉"); //// $pool->shutdown(); //// } //// }); // Swoole\Timer::tick(1000, function(){ // logs("进程进入定时器-----------------"); // }); // } catch (\Exception $e) { // logs("进程ID:".$workerId.",定时器错误:".$e->getMessage()); // } // try { // $redis = new \Redis(); // $redis->pconnect('127.0.0.1', 6379); // $key = "key1\n"; // while (true) { // $msg = $redis->brpop($key, 2); // if ( $msg == null) continue; // var_dump($msg); // } // } catch (\Exception $e) { // echo $e->getMessage()."\n"; // echo "$workerId 发生错误终止\n"; // //; } }); $pool->on("WorkerStop", function ($pool, $workerId) { echo "Worker#{$workerId} is stopped\n"; // $pool->shutdown(); }); $pool->start(); $redis = getRedis(); $kes = 'redis_masterpid_key'; $workerId = $redis->get($kes); if($type == 'reload') { if($workerId > 0) { Swoole\Process::kill($workerId,SIGUSR1);//平滑重启服务work进程 logs("重启进程ID:".$workerId); } else { logs("重启进程ID:".$workerId."失败。进程ID有问题"); } } else { if($workerId > 0) { Swoole\Process::kill($workerId);//终止服务 $redis->set($kes,0); logs("结束进程ID:".$workerId); } else { logs("结束进程ID:".$workerId."失败。进程ID有问题"); } } ``` ### 你期待的结果是什么?实际看到的错误信息又是什么? 运行 netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}' 的到 ESTABLISHED 91 TIME_WAIT 318
发布于3年前 · 40 次浏览 · 来自
提问
xuexi
### 问题描述 Swoole\Process\Pool 产生大量 TIME_WAIT 进程,不超过400个 一直在 400以下波动,一启动,就从0增加到 390,然后一直波动400以下 目前初学。各位大佬勿怪 ### Swoole版本,PHP版本,以及操作系统版本信息 PHP7.4.8 swoole 4.7.1 ### 相关代码 ```php <?php error_reporting(E_ALL); ini_set("display_errors","On"); ini_set('date.timezone','Asia/Shanghai'); //$a = [ // ['id'=>7], // ['id'=>17], // ['id'=>27], // ['id'=>37], // ['id'=>47], //]; //echo json_encode($a);exit; //$redis = getRedis(); //$A = $redis->lPop('aaa'); //print_r($A);exit; function getAll($sql) { $mysql = new mysqli('10.28.41.244','huangchunlong','47M$FQa3#GeWqfX#m8ssiCui!4KQ34fg','test'); if(!$mysql) exit("connect error:".mysqli_connect_error()); $rs = $mysql->query($sql); $c = array(); while($r = $rs->fetch_assoc()){ $c[] = $r; } $mysql->close(); return $c; } function getRedis() { $redis = new Redis(); $redis->connect("10.28.41.244", 7000); //pconnect连接 $redis->auth("fxrXQ%gL%Kh7Hz42"); return $redis; } function getRow($sql) { $mysql = new mysqli('10.28.41.244','huangchunlong','47M$FQa3#GeWqfX#m8ssiCui!4KQ34fg','test'); if(!$mysql) exit("connect error:".mysqli_connect_error()); $rs = $mysql->query($sql); $row = $rs->fetch_assoc(); $mysql->close(); return $row; } //记录日志 单元测试用 $content 日志内容 $file日志名称 保存在public/runtime/logic目录下 function logs($content, $file='logic.log') { $now = date('Y-m-d H:i:s'); $content = "[{$now}]: {$content}\r\n"; $path = '/runtime/'; $file = $path.$file; if(!is_dir($path)) mkdir($path,0777,true); error_log($content,3,$file); } //需要处理的计划任务,可以是Redis队列或者其他 //redis 长久连接。需要在底层用发 比如POP 等加try catech 判断错误异常原因,然后重新连接,在去执行方法 /* 1.开启2个进程,一个就是这个进程,另外一个就是检测进程,检测配置的更新时间是否更新。更新后发送信号给POLL进程池 2.he和监控程序一起加入supvisor里面 * */ //获取当前主进程ID,写入文档或者redis $redis = getRedis(); $kes = 'redis_masterpid_key'; $redis->set($kes, getmypid()); $workerNum = 3; $pool = new Swoole\Process\Pool($workerNum); $pool->set([ 'max_wait_time' => 60, 'reload_async' => true, ]); cli_set_process_title('mqlistenkey'); $pool->on("WorkerStart", function ($pool, $workerId) use($workerNum) { //开启定时器 if($workerId == 0) { echo "wsohis0000000000000000\n\n"; } echo "Worker#{$workerId} ".getmypid()." is started\n"; $process = $pool->getProcess(); // //工作进程为异步模式,请使用 Swoole\Process::signal 监听信号 //工作进程为同步模式,请使用 pcntl_signal 和 pcntl_signal_dispatch 监听信号 pcntl_signal(SIGTERM, function ($sign) use ($process,$workerId) { logs("进程ID:".$workerId.",监听到信号$sign ,终止"); $process->exit(); }); //// $process->exec('/opt/extend/php74/bin/php', ['-r', 'var_dump(swoole_version());']); //执行这个下面不执行 /// $childProcess->exec('/usr/local/bin/php', ['/var/www/project/yii-best-practice/cli/yii', 't/index', '-m=123', 'abc', 'xyz']); // exec 系统调用 // print_r($process->pid); /** Swoole\Process Object ( [pipe] => [msgQueueId] => [msgQueueKey] => [pid] => 16968 [id] => 1 [callback:Swoole\Process:private] => ) */ // if($workerId !=0) { // // } else { // // } $redis = getRedis(); $arr = getAll("select * from mq where id%$workerNum=$workerId and status=0"); $key = "hash_redis_".$workerId; $max = []; foreach ($arr as $v) { $max[] = $v['u_t']; $v['time'] = date('Y-d-d H:i:s'); $redis->hSet($key,$v['id'],json_encode($v)); //这里请求外部接口。。。执行一系列操作。或者是去获取Redis配置 } sleep(1); if(!empty($max)) { $lastut = max($max); } else { $lastut = 0; } logs("进程ID:".$workerId.",当前最大UT:".$lastut); pcntl_signal_dispatch(); // try { //// Swoole\Timer::tick(2000, function($timer_id,$lastut,$workerNum,$workerId,$pool){ //// logs("进程ID:".$workerId.",进入定时器-----------------"); //// $last = getRow("select u_t from mq where id%$workerNum=$workerId and status=0 order by u_t desc limit 1"); //// logs("进程ID:".$workerId.",定时器查询最大UT:".$last); //// if($last['u_t'] > $lastut && $lastut != 0) { //// logs("进程ID:".$workerId.",进程杀掉"); //// $pool->shutdown(); //// } //// }); // Swoole\Timer::tick(1000, function(){ // logs("进程进入定时器-----------------"); // }); // } catch (\Exception $e) { // logs("进程ID:".$workerId.",定时器错误:".$e->getMessage()); // } // try { // $redis = new \Redis(); // $redis->pconnect('127.0.0.1', 6379); // $key = "key1\n"; // while (true) { // $msg = $redis->brpop($key, 2); // if ( $msg == null) continue; // var_dump($msg); // } // } catch (\Exception $e) { // echo $e->getMessage()."\n"; // echo "$workerId 发生错误终止\n"; // //; } }); $pool->on("WorkerStop", function ($pool, $workerId) { echo "Worker#{$workerId} is stopped\n"; // $pool->shutdown(); }); $pool->start(); $redis = getRedis(); $kes = 'redis_masterpid_key'; $workerId = $redis->get($kes); if($type == 'reload') { if($workerId > 0) { Swoole\Process::kill($workerId,SIGUSR1);//平滑重启服务work进程 logs("重启进程ID:".$workerId); } else { logs("重启进程ID:".$workerId."失败。进程ID有问题"); } } else { if($workerId > 0) { Swoole\Process::kill($workerId);//终止服务 $redis->set($kes,0); logs("结束进程ID:".$workerId); } else { logs("结束进程ID:".$workerId."失败。进程ID有问题"); } } ``` ### 你期待的结果是什么?实际看到的错误信息又是什么? 运行 netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}' 的到 ESTABLISHED 91 TIME_WAIT 318
赞
0
分享
收藏
提问
分享
讨论
建议
公告
开发框架
CodeGalaxy
评论
2021-10-12
xuexi
下面那段代码 不是在同一个文件的,我准备在 workid=0 开启定时器 把下面代码放进去,不知道对不对,球大佬指点
赞
0
回复
2021-10-15
Rango
`TIME_WAIT` 没关系的,这个表示存在 `TCP` 短连接,系统会将本地端口保留一段时间。
赞
0
回复
微信公众号
热门内容
暂无回复的问答
- CodeGalaxy K3s 轻量集群节点之间如何实现负载均衡
- 关于openssl CURL WARNING swSSL_connect: SSL_connect(fd=69) failed. Error: error:141A318A:SSL routines:tls_process_ske_dhe:dh key too small[1|394]
- 多个模型如何进行事务异常回退?
- websocket开启wss报错
- 协程tcp服务器如何使用多进程?recv()方法接收信息,打印出来的pid一直是同一个。没用使用到多进程啊。