一:信号监听

信号:由用户、系统或者进程发给目标进程的信息,以通知目标进程某个状态的改变或系统异常

信号查看:kill -l

SIGHUP     终止进程     终端线路挂断
SIGINT     终止进程     中断进程
SIGKILL   终止进程     杀死进程
SIGPIPE   终止进程      向一个没有读进程的管道写数据
SIGALARM   终止进程     计时器到时
SIGTERM   终止进程      软件终止信号
SIGSTOP   停止进程     非终端来的停止信号
SIGTSTP   停止进程      终端来的停止信号
SIGCONT   忽略信号     继续执行一个停止的进程
SIGURG   忽略信号      I/O紧急信号
SIGIO     忽略信号     描述符上可以进行I/O
SIGPROF   终止进程     统计分布图用计时器到时
SIGUSR1   终止进程      用户定义信号1
SIGUSR2   终止进程     用户定义信号2
SIGVTALRM 终止进程     虚拟计时器到时

swoole热重启命令:

1、kill -SIGTERM|-15 master_pid  终止Swoole程序,一种优雅的终止信号,会待进程执行完当前程序之后中断,而不是直接干掉进程
2、kill -USR1|-10 master_pid 重启所有的Worker进程
3、kill -USR2|-12 master_pid 重启所有的Task Worker进程  

重启子进程、拉起子进程代码:

<?php
class Worker {
//监听socket
protected $socket = NULL;
//连接事件回调
public $onConnect = NULL;
//接收消息事件回调
public $onMessage = NULL;
public $workerNum = 4;
public $addr;
public $worker_pid;
public $master_pid; public function __construct($socket_address) {
$this->addr=$socket_address;
$this->master_pid = posix_getpid();
} //创建子进程
public function fork($worker_num) {
for ($i = 0; $i < $worker_num; $i++) {
$pid = pcntl_fork();
if ($pid < 0) {
exit('创建失败');
} else if ($pid > 0) {
//存储子进程id
$this->worker_pid[]=$pid;
} else {
$this->accept();
exit();
}
}
} public function accept() {
$opts = array(
'socket' => array(
'backlog' => '10240',
),
); $context = stream_context_create($opts); stream_context_set_option($context,'socket','so_reuseport',1); $this->socket = stream_socket_server($this->addr,$error,$errstr, STREAM_SERVER_BIND|STREAM_SERVER_LISTEN,$context);
swoole_event_add($this->socket, function ($fd) {
//服务端接收客户端请求
$clientSocket = stream_socket_accept($this->socket);
if (!empty($clientSocket) && is_callable($this->onConnect)) {
call_user_func($this->onConnect, $clientSocket);
}
swoole_event_add($clientSocket, function ($fd) {
$buffer = fread($fd, 65535);
//如果数据为空,或者为false,不是资源类型
if (empty($buffer)) {
if (feof($fd) || !is_resource($fd)) {
//触发关闭事件
fclose($fd);
}
}
if (!empty($buffer) && is_callable($this->onMessage)) {
call_user_func($this->onMessage, $fd, $buffer);
}
});
});
}
/**
* 捕获信号
* 监视worker进程.拉起进程
*/
public function monitorWorkers(){
//注册信号事件回调,是不会自动执行的
pcntl_signal(SIGUSR1, array($this, 'signalHandler'),false); //重启woker进程信号 // pcntl_signal(SIGUSR1,array($this,'signalHandler'),false); //重启worker进程信号
$status = 0;
//回收子进程
while(1){
//reload
// 当发现信号队列,一旦发现有信号就会触发进程绑定事件回调
pcntl_signal_dispatch();
$pid = pcntl_wait($status); //当信号到达之后就会被中断
//ctrl+c
//如果进程不是正常情况下的退出,重启子进程,我想要维持子进程个数
if($pid>1 && $pid != $this->master_pid && !pcntl_wifexited($status)){
$index=array_search($pid,$this->worker_pid);
$this->fork(1);
var_dump('拉起子进程');
unset($this->worker_pid[$index]);
}
pcntl_signal_dispatch();
//进程重启的过程当中会有新的信号过来,如果没有调用pcntl_signal_dispatch,信号不会被处理
}
} public function signalHandler($sigo){
switch ($sigo){
case SIGUSR1:
$this->reload();
echo '收到重启信号';
break;
}
} public function reload(){
foreach($this->worker_pid as $index =>$pid){
posix_kill($pid,SIGKILL);
var_dump("杀掉的子进程$pid");
unset($this->worker_pid[$index]);
$this->fork(1);
}
} public function start() {
$this->fork($this->workerNum);
$this->monitorWorkers(); //监视程序,捕获信号,监视worker进程 }
} $worker = new Worker('tcp://0.0.0.0:9801'); $worker->onConnect = function ($args) {
echo "新的连接来了.{$args}.PHP_EOL";
};
$worker->onMessage = function ($conn, $message) {
// var_dump($conn, $message);
$content = "hello word qwe";
$http_resonse = "HTTP/1.1 200 OK\r\n";
$http_resonse .= "Content-Type: text/html;charset=UTF-8\r\n";
$http_resonse .= "Connection: keep-alive\r\n";
$http_resonse .= "Server: php socket server\r\n";
$http_resonse .= "Content-length: " . strlen($content) . "\r\n\r\n";
$http_resonse .= $content;
fwrite($conn, $http_resonse);
};
$worker->start();

cli运行:

二:inotify热重启

inotify:是linux内核提供的一组系统调用,她可以监控文件系统操作,比如文件或者目录的创建、读取、写入、权限修改、删除等

    public function start() {
//获取配置文件
$this->watch();
$this->fork($this->workerNum);
$this->monitorWorkers(); //监视程序,捕获信号,监视worker进程
} /**
* 文件监视,自动重启
*/
protected function watch(){
$init=inotify_init(); //初始化
$files=get_included_files();
foreach ($files as $file){
inotify_add_watch($init,$file,IN_MODIFY); //监视相关的文件
}
//监听
swoole_event_add($init,function ($fd){
$events=inotify_read($fd);
if(!empty($events)){
posix_kill($this->master_pid,SIGUSR1);
}
});
}

swoole(5)信号监听、热重启的更多相关文章

  1. swoole多端口监听

    今天测试swoole写webserver实现多端口监听.记录下爬过的坑:关于tcp协议监听触发不到receive!!!!! 首先上服务端代码 class Http { /** * 服务实例 * @va ...

  2. 监听服务器 重启apache

    import requests import os import time url = 'http://www.ydyigo.com/findPwd.php' def get_server_statu ...

  3. Oracle 监听器日志文件过大导致监听异常

    Oracle 监听器日志文件过大导致监听异常 db版本:11.2.0.1 os版本:windows2008 现象: 应用异常,无法连接数据库.登陆数据库服务器,查看监听已经断掉.尝试重启监听,重启失败 ...

  4. java监听事件

    2014年2月23日 09:51:54 成功添加了打开官网的事件, 回头研究下,那个打开url的类 java的System.getProperty()方法可以获取的值 ################ ...

  5. ORACLE的监听日志太大,客户端无法连接

    数据库sqlplus能连接,plsql连接失败,也不报错,就定位到了是不是监听出了什么问题,删除监听,重建监听,重启监听,各种尝试都没解决问题. 却是监听日志太大导致的问题,一下是处理步骤: 查看监听 ...

  6. oracle连接错误:ORA-12514: TNS: 监听程序当前无法识别连接描述符中请求的服务解决

    自己的解决办法是,把数据库连接字符串的默认SID_NAME = ORCL改为 sid_name =test(自己安装数据库时候改的名字).即可正常连接. 网上搜罗的其他问题:把监听服务重启下.(自己的 ...

  7. java 监听控制台输入

    分享一下我写的java监听控制台输入并可以给出响应的功能. 很多时候需要监听控制台的输入内容,相当于信号监听,根据输入的内容做出相应的动作,这里给出我的一个简单实现. 要注意的是:监听得到的消息中前后 ...

  8. libvert开启TCP监听

    1.设置libvirtd 编辑/etc/libvirt/libvirtd.conf listen_tls = 0 listen_tcp = 1 auth_tcp="none" tc ...

  9. 安装完oracle重新启动后报ORA-12514: TNS: 监听程序当前无法识别连接描述符中请求的服务(重启前正常)

    安装完oracle重新启动后报ORA-12514: TNS: 监听程序当前无法识别连接描述符中请求的服务(重启前正常) 刚安装完后用plSql登录正常. 在dos命令行下 输入  sqlplus 用户 ...

  10. Java线程监听,意外退出线程后自动重启

    Java线程监听,意外退出线程后自动重启 某日,天朗气清,回公司,未到9点,刷微博,顿觉问题泛滥,惊恐万分! 前一天写了一个微博爬行程序,主要工作原理就是每隔2分钟爬行一次微博,获取某N个关注朋友微博 ...

随机推荐

  1. shell 将文件内容读取到 数组中

    #!/bin/bash prod_file=/home/vmuser/linbo/kettleDemo/job/test/CA-20201224.csv test_file=/home/vmuser/ ...

  2. 【转载】茅台巽风app地图详解,做任务不迷路,纯手绘

    茅台发布了新的app"巽风" 根据"巽值"的排名,发放20000个虎年茅台的资格,还是可以玩一玩的 哪些途径获取"巽值" 1.做任务,和游戏 ...

  3. Vetur can't find `tsconfig.json` or `jsconfig.json` in XXX

    vue界面启动项目 visual code报错 如下图,找到 Ignore Project Warning 前边打上对勾

  4. Uniapp仿ChatGPT Stream流式输出(非Websocket)

    前言 最近写一个chagpt小程序,流式输出可以使用websocket也可以使用stream来实现,这里就不折腾websocket的了,我发现uniapp实现流式输出的方式挺多的,主要是有些小程序还不 ...

  5. 让我看看有多少人不知道Vue3中也能实现高阶组件HOC

    前言 高阶组件HOC在React社区是非常常见的概念,但是在Vue社区中却是很少人使用.主要原因有两个:1.Vue中一般都是使用SFC,实现HOC比较困难.2.HOC能够实现的东西,在Vue2时代mi ...

  6. 开箱你的 AI 语音女友「GitHub 热点速览」

    随着大模型 API 服务的不断丰富,开发者无需再依赖昂贵的硬件,也能轻松开发出拥有强大 AI 能力的应用.这不仅降低了技术门槛,也激发了极客们的创造力. 就比如上周飙升 1.5k Star 的开源项目 ...

  7. linux-杂项

    1.常用基础 防火墙systemctl status firewalldsystemctl stop firewalldsystemctl start firewalld find / -size + ...

  8. runoob-pandas(python)

    https://www.runoob.com/pandas/pandas-tutorial.html Pandas 教程 Pandas 是 Python 语言的一个扩展程序库,用于数据分析. Pand ...

  9. tmux中的vim无法多彩高亮显示关键字

    1. 问题描述 vim安装了interastingwords插件,在mobaxterm中的session可以正常显示多彩关键字,但是使用tmux登录session,只能显示两个颜色 2. 解决办法 这 ...

  10. layui table表格单元格动态合并,并设置隔行变色

    layui table表格单元格动态合并,并设置隔行变色,此代码只针对嵌套数组只有一层的时候有效,多个数组嵌套还在冥想当中!! 需求描述 我们知道在layui插件官方平台有个可以无限极单元格合并的模块 ...