一:信号监听

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

信号查看: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. 中电金信新捷报:银行客户资源管理领域No.1

    春暖花开,捷报频传 近日,中电金信 客户关系管理系统(CRM) 接连中标 让我们共同见证这波喜讯 01 中电金信凭借优秀的解决方案和丰富的服务案例经验,成功中标某全国性股份制银行同业CRM实施服务采购 ...

  2. 德哥的PostgreSQL私房菜

    德哥的PostgreSQL私房菜 - 史上最屌PG资料合集-博客-云栖社区-阿里云 : https://yq.aliyun.com/articles/59251 https://github.com/ ...

  3. 武装你的WEBAPI-OData使用Endpoint

    本文属于 OData 系列文章 Introduction 更新: 由于新版的 OData 已经默认使用了 endpoint 模式(Microsoft.AspNetCore.OData 8.0.0),不 ...

  4. iOS app 自动化测试,appium inspector 启动会话报错:Failed to create session. An unknown server-side error occurred while processing the command. Original error: '12.5.5' does not exist in the list of simctl SDKs.

    报错内容:Failed to create session. An unknown server-side error occurred while processing the command. O ...

  5. 如何在 Ubuntu 20.04 上安装 MySQL

    https://dev.mysql.com/downloads/mysql/ 简介: MySQL是最流行的开源关系数据库管理系统.它速度快,容易使用,容易扩展,并且流行的LAMP和LEMP的一部分. ...

  6. maven:Could not transfer artifact from/to maven-default-http-blocker (http://0.0.0.0/): Blocked m...

    今天在拉完项目后拉取包的过程中,maven报错: Could not transfer artifact from/to 对应的包 maven-default-http-blocker (http:/ ...

  7. 创建企业级地理数据库——PostgreSQL版

    创建PostgreSQL空间数据库 填写相应的参数,选择授权文件 报错 默认安装postgresql后,执行以上操作报错 "You must copy the latest ST_GEOME ...

  8. 关于 static 和 final 的一些理解

    今天主要回顾一下 static 和 final 这两个关键字. 1. static  -  静态 修饰符 - 用于修饰数据(变量.对象).方法.代码块以及内部类.         1.1 静态变量 用 ...

  9. Hbase shell学习

    通过Shell工具可以对云数据库HBase进行数据管理,包括建表.插入数据.删除数据和删除表等操作,本文介绍Shell的基本使用命令. 访问配置 如果使用的是云数据库HBase标准版,基本环境的配置操 ...

  10. K_V键值存储对比

    memcached-键值存储 redis-键值存储 RocksDB-键值存储 KeyDB-键值存储 DynamoDB-键值存储 levelDB-键值存储 etcd-键值存储 Redis与其他数据库对比 ...