PHP網(wǎng)絡(luò)服務(wù)器模型 重啟worker 進(jìn)程

PHP網(wǎng)絡(luò)服務(wù)器模型 重啟worker 進(jìn)程

class Worker{

? ? //監(jiān)聽socket

? ? protected $socket = NULL;

? ? //連接事件回調(diào)

? ? public $onConnect = NULL;

? ? public? $reusePort=1;

? ? //接收消息事件回調(diào)

? ? public $onMessage = NULL;

? ? public $workerNum=3; //子進(jìn)程個數(shù)

? ? public? $allSocket; //存放所有socket

? ? public? $addr;

? ? protected $worker_pid; //子進(jìn)程pid

? ? protected? $master_pid;//主進(jìn)程id

? ? public function __construct($socket_address) {

? ? ? ? //監(jiān)聽地址+端口

? ? ? ? $this->addr=$socket_address;

? ? ? ? $this->master_pid=posix_getpid();

? ? }

? ? public function start() {

? ? ? ? //獲取配置文件

? ? ? ? $this->watch();

? ? ? ? $this->fork($this->workerNum);

? ? ? ? $this->monitorWorkers(); //監(jiān)視程序,捕獲信號,監(jiān)視worker進(jìn)程

? ? }

? ? /**

* 文件監(jiān)視,自動重啟

*/

? ? protected? function watch(){

? ? ? ? $init=inotify_init(); //初始化

? ? ? ? $files=get_included_files();

? ? ? ? foreach ($files as $file){

? ? ? ? ? ? inotify_add_watch($init,$file,IN_MODIFY); //監(jiān)視相關(guān)的文件

? ? ? ? }

? ? ? ? //監(jiān)聽

? ? ? ? swoole_event_add($init,function ($fd){

? ? ? ? ? ? $events=inotify_read($fd);

? ? ? ? ? ? if(!empty($events)){

? ? ? ? ? ? ? ? posix_kill($this->master_pid,SIGUSR1);

? ? ? ? ? ? }

? ? ? ? });

? ? }

? ? /**

* 捕獲信號

* 監(jiān)視worker進(jìn)程.拉起進(jìn)程

*/

? ? public? function monitorWorkers(){

? ? ? ? //注冊信號事件回調(diào),是不會自動執(zhí)行的

// reload

? ? ? ? pcntl_signal(SIGUSR1, array($this, 'signalHandler'),false); //重啟woker進(jìn)程信號

//ctrl+c

? ? ? ? $status=0;

? ? ? ? while (1){

? ? ? ? ? ? // 當(dāng)發(fā)現(xiàn)信號隊列,一旦發(fā)現(xiàn)有信號就會觸發(fā)進(jìn)程綁定事件回調(diào)

? ? ? ? ? ? pcntl_signal_dispatch();

? ? ? ? ? ? $pid = pcntl_wait($status); //當(dāng)信號到達(dá)之后就會被中斷

//如果進(jìn)程不是正常情況下的退出,重啟子進(jìn)程,我想要維持子進(jìn)程個數(shù)

//? ? ? ? ? ? if($pid>1 && $pid != $this->master_pid? && !pcntl_wifexited($status)){

//? ? ? ? ? ? ? ? ? ? $index=array_search($pid,$this->worker_pid);

//? ? ? ? ? ? ? ? ? ? $this->fork(1);

//? ? ? ? ? ? ? ? ? ? var_dump('拉起子進(jìn)程');

//? ? ? ? ? ? ? ? ? ? unset($this->worker_pid[$index]);

//? ? ? ? ? ? }

? ? ? ? ? ? pcntl_signal_dispatch();

? ? ? ? ? ? //進(jìn)程重啟的過程當(dāng)中會有新的信號過來,如果沒有調(diào)用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(); //創(chuàng)建成功會返回子進(jìn)程id

? ? ? ? ? ? if($pid<0){

? ? ? ? ? ? ? ? exit('創(chuàng)建失敗');

? ? ? ? ? ? }else if($pid>0){

? ? ? ? ? ? ? ? //父進(jìn)程空間背率,返回子進(jìn)程id

? ? ? ? ? ? ? ? $this->worker_pid[]=$pid;

? ? ? ? ? ? }else{ //返回為0子進(jìn)程空間

? ? ? ? ? ? ? ? $this->accept();//子進(jìn)程負(fù)責(zé)接收客戶端請求

? ? ? ? ? ? ? ? exit;

? ? ? ? ? ? }

}

? ? ? ? //放在父進(jìn)程空間胧奔,結(jié)束的子進(jìn)程信息,阻塞狀態(tài)

? ? }

? ? public? function? accept(){

? ? ? ? $opts = array(

? ? ? ? ? ? 'socket' => array(

? ? ? ? ? ? ? ? 'backlog' =>10240, //成功建立socket連接的等待個數(shù)

? ? ? ? ? ? ),

? ? ? ? );

? ? ? ? $context = stream_context_create($opts);

? ? ? ? //開啟多端口監(jiān)聽,并且實現(xiàn)負(fù)載均衡

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

? ? ? ? //第一個需要監(jiān)聽的事件(服務(wù)端socket的事件),一旦監(jiān)聽到可讀事件之后會觸發(fā)

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

? ? ? ? ? ? $clientSocket=stream_socket_accept($fd);

? ? ? ? ? ? //觸發(fā)事件的連接的回調(diào)

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

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

? ? ? ? ? ? }

? ? ? ? ? ? //監(jiān)聽客戶端可讀

? ? ? ? ? ? swoole_event_add($clientSocket,function ($fd){

? ? ? ? ? ? ? ? //從連接當(dāng)中讀取客戶端的內(nèi)容

? ? ? ? ? ? ? ? $buffer=fread($fd,1024);

? ? ? ? ? ? ? ? //如果數(shù)據(jù)為空杭棵,或者為false,不是資源類型

? ? ? ? ? ? ? ? if(empty($buffer)){

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

? ? ? ? ? ? ? ? ? ? ? ? //觸發(fā)關(guān)閉事件

? ? ? ? ? ? ? ? ? ? ? ? fclose($fd);

? ? ? ? ? ? ? ? ? ? }

}

? ? ? ? ? ? ? ? //正常讀取到數(shù)據(jù),觸發(fā)消息接收事件,響應(yīng)內(nèi)容

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

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

? ? ? ? ? ? ? ? }

? ? ? ? ? ? });

? ? ? ? });

? ? }

? ? /**

* 重啟worker進(jìn)程

*/

? ? public? function reload(){

? ? ? ? foreach ($this->worker_pid as $index=>$pid){

? ? ? ? ? ? posix_kill($pid,SIGKILL); //結(jié)束進(jìn)程

? ? ? ? ? ? var_dump("殺掉的子進(jìn)程",$pid);

? ? ? ? ? ? unset($this->worker_pid[$index]);

? ? ? ? ? ? $this->fork(1); //重新拉起worker

? ? ? ? }

}

? ? //捕獲信號之后重啟worker進(jìn)程

}

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

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

//開啟多進(jìn)程的端口監(jiān)聽

$worker->reusePort = true;

//連接事件

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

? ? //echo '連接事件觸發(fā)',(int)$fd,PHP_EOL;

};

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

? ? //echo '連接事件觸發(fā)',(int)$fd,PHP_EOL;

};

//消息接收

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

? ? //事件回調(diào)當(dāng)中寫業(yè)務(wù)邏輯

// $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(); //啟動

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末客年,一起剝皮案震驚了整個濱河市坊罢,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌知市,老刑警劉巖傻盟,帶你破解...
    沈念sama閱讀 218,451評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異嫂丙,居然都是意外死亡莫杈,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,172評論 3 394
  • 文/潘曉璐 我一進(jìn)店門奢入,熙熙樓的掌柜王于貴愁眉苦臉地迎上來筝闹,“玉大人,你說我怎么就攤上這事腥光」厍辏” “怎么了?”我有些...
    開封第一講書人閱讀 164,782評論 0 354
  • 文/不壞的土叔 我叫張陵武福,是天一觀的道長议双。 經(jīng)常有香客問我,道長捉片,這世上最難降的妖魔是什么平痰? 我笑而不...
    開封第一講書人閱讀 58,709評論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮伍纫,結(jié)果婚禮上宗雇,老公的妹妹穿的比我還像新娘。我一直安慰自己莹规,他們只是感情好赔蒲,可當(dāng)我...
    茶點故事閱讀 67,733評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般舞虱。 火紅的嫁衣襯著肌膚如雪欢际。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,578評論 1 305
  • 那天矾兜,我揣著相機與錄音损趋,去河邊找鬼。 笑死椅寺,一個胖子當(dāng)著我的面吹牛浑槽,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播配并,決...
    沈念sama閱讀 40,320評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼括荡,長吁一口氣:“原來是場噩夢啊……” “哼高镐!你這毒婦竟也來了溉旋?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,241評論 0 276
  • 序言:老撾萬榮一對情侶失蹤嫉髓,失蹤者是張志新(化名)和其女友劉穎观腊,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體算行,經(jīng)...
    沈念sama閱讀 45,686評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡梧油,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,878評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了州邢。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片儡陨。...
    茶點故事閱讀 39,992評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖量淌,靈堂內(nèi)的尸體忽然破棺而出骗村,到底是詐尸還是另有隱情,我是刑警寧澤呀枢,帶...
    沈念sama閱讀 35,715評論 5 346
  • 正文 年R本政府宣布胚股,位于F島的核電站,受9級特大地震影響裙秋,放射性物質(zhì)發(fā)生泄漏琅拌。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,336評論 3 330
  • 文/蒙蒙 一摘刑、第九天 我趴在偏房一處隱蔽的房頂上張望进宝。 院中可真熱鬧,春花似錦枷恕、人聲如沸即彪。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,912評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽隶校。三九已至漏益,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間深胳,已是汗流浹背绰疤。 一陣腳步聲響...
    開封第一講書人閱讀 33,040評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留舞终,地道東北人轻庆。 一個月前我還...
    沈念sama閱讀 48,173評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像敛劝,于是被迫代替她去往敵國和親余爆。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,947評論 2 355