PHP网络服务器模型 重启worker 进程

PHP网络服务器模型 重启worker 进程

class Worker{

    //监听socket

    protected $socket = NULL;

    //连接事件回调

    public $onConnect = NULL;

    public  $reusePort=1;

    //接收消息事件回调

    public $onMessage = NULL;

    public $workerNum=3; //子进程个数

    public  $allSocket; //存放所有socket

    public  $addr;

    protected $worker_pid; //子进程pid

    protected  $master_pid;//主进程id

    public function __construct($socket_address) {

        //监听地址+端口

        $this->addr=$socket_address;

        $this->master_pid=posix_getpid();

    }

    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);

            }

        });

    }

    /**

* 捕获信号

* 监视worker进程.拉起进程

*/

    public  function monitorWorkers(){

        //注册信号事件回调,是不会自动执行的

// reload

        pcntl_signal(SIGUSR1, array($this, 'signalHandler'),false); //重启woker进程信号

//ctrl+c

        $status=0;

        while (1){

            // 当发现信号队列,一旦发现有信号就会触发进程绑定事件回调

            pcntl_signal_dispatch();

            $pid = pcntl_wait($status); //当信号到达之后就会被中断

//如果进程不是正常情况下的退出,重启子进程,我想要维持子进程个数

//            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 fork($worker_num){

        for ($i=0;$i<$worker_num;$i++){

            $test=include 'index.php';

            var_dump($test);

            $pid=pcntl_fork(); //创建成功会返回子进程id

            if($pid<0){

                exit('创建失败');

            }else if($pid>0){

                //父进程空间,返回子进程id

                $this->worker_pid[]=$pid;

            }else{ //返回为0子进程空间

                $this->accept();//子进程负责接收客户端请求

                exit;

            }

}

        //放在父进程空间,结束的子进程信息,阻塞状态

    }

    public  function  accept(){

        $opts = array(

            'socket' => array(

                'backlog' =>10240, //成功建立socket连接的等待个数

            ),

        );

        $context = stream_context_create($opts);

        //开启多端口监听,并且实现负载均衡

        stream_context_set_option($context,'socket','so_reuseport',1);

        stream_context_set_option($context,'socket','so_reuseaddr',1);

        $this->socket=stream_socket_server($this->addr,$errno,$errstr,STREAM_SERVER_BIND|STREAM_SERVER_LISTEN,$context);

        //第一个需要监听的事件(服务端socket的事件),一旦监听到可读事件之后会触发

        swoole_event_add($this->socket,function ($fd){

            $clientSocket=stream_socket_accept($fd);

            //触发事件的连接的回调

            if(!empty($clientSocket) && is_callable($this->onConnect)){

                call_user_func($this->onConnect,$clientSocket);

            }

            //监听客户端可读

            swoole_event_add($clientSocket,function ($fd){

                //从连接当中读取客户端的内容

                $buffer=fread($fd,1024);

                //如果数据为空,或者为false,不是资源类型

                if(empty($buffer)){

                    if(!is_resource($fd) || feof($fd) ){

                        //触发关闭事件

                        fclose($fd);

                    }

}

                //正常读取到数据,触发消息接收事件,响应内容

                if(!empty($buffer) && is_callable($this->onMessage)){

                    call_user_func($this->onMessage,$fd,$buffer);

                }

            });

        });

    }

    /**

* 重启worker进程

*/

    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); //重新拉起worker

        }

}

    //捕获信号之后重启worker进程

}

//ps -ef | grep php | grep -v grep | awk '{print $2}' | xargs kill -s 9

$worker = new Worker('tcp://0.0.0.0:9800');

//开启多进程的端口监听

$worker->reusePort = true;

//连接事件

$worker->onConnect = function ($fd) {

    //echo '连接事件触发',(int)$fd,PHP_EOL;

};

$worker->onTask = function ($fd) {

    //echo '连接事件触发',(int)$fd,PHP_EOL;

};

//消息接收

$worker->onMessage = function ($conn, $message) {

    //事件回调当中写业务逻辑

// $a=include 'index.php';

// var_dump($a);

//var_dump($conn,$message);

    $content="我是peter";

    $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(); //启动

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,530评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,403评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,120评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,770评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,758评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,649评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,021评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,675评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,931评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,751评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,410评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,004评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,969评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,042评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,493评论 2 343