예제 #1
0
 /**
  * 处理业务
  * @see Worker::dealProcess()
  */
 public function dealProcess($buffer)
 {
     $buffer = trim($buffer);
     $ip = $this->getRemoteIp();
     if ($ip != '127.0.0.1' && $buffer == 'status') {
         \Man\Core\Lib\Log::add("IP:{$ip} {$buffer}");
     }
     // 判断是否认证过
     $this->adminAuth[$this->currentDealFd] = !isset($this->adminAuth[$this->currentDealFd]) ? 0 : $this->adminAuth[$this->currentDealFd];
     if ($this->adminAuth[$this->currentDealFd] < 3) {
         if ($buffer != \Man\Core\Lib\Config::get($this->workerName . '.password')) {
             if (++$this->adminAuth[$this->currentDealFd] >= 3) {
                 $this->sendToClient("Password Incorrect \n");
                 $this->closeClient($this->currentDealFd);
                 return;
             }
             $this->sendToClient("Please Try Again\n");
             return;
         } else {
             $this->adminAuth[$this->currentDealFd] = time();
             $this->sendToClient("Hello Admin \n");
             return;
         }
     }
     // 单独停止某个worker进程
     if (preg_match("/kill (\\d+)/", $buffer, $match)) {
         $pid = $match[1];
         $this->sendToClient("Kill Pid {$pid}\n");
         if (!posix_kill($pid, SIGHUP)) {
             $this->sendToClient("Pid Not Exsits\n");
         }
         return;
     }
     $master_pid = file_get_contents(WORKERMAN_PID_FILE);
     switch ($buffer) {
         // 展示统计信息
         case 'status':
             $status = $this->getMasterStatus();
             if (empty($status)) {
                 $this->sendToClient("Can not get Master status, Extension sysvshm or sysvmsg may not enabled\n");
                 return;
             }
             $worker_pids = $this->getWorkerPidMap();
             $pid_worker_name_map = $this->getPidWorkerMap();
             foreach ($worker_pids as $worker_name => $pid_array) {
                 if ($this->maxWorkerNameLength < strlen($worker_name)) {
                     $this->maxWorkerNameLength = strlen($worker_name);
                 }
             }
             foreach (\Man\Core\Lib\Config::getAllWorkers() as $worker_name => $config) {
                 if (!isset($config['listen'])) {
                     continue;
                 }
                 if ($this->maxAddressLength < strlen($config['listen'])) {
                     $this->maxAddressLength = strlen($config['listen']);
                 }
             }
             $msg_type = $message = 0;
             // 将过期的消息读出来,清理掉
             if (\Man\Core\Master::getQueueId()) {
                 while (@msg_receive(\Man\Core\Master::getQueueId(), self::MSG_TYPE_STATUS, $msg_type, 1000, $message, true, MSG_IPC_NOWAIT)) {
                 }
             }
             $loadavg = sys_getloadavg();
             $this->sendToClient("---------------------------------------GLOBAL STATUS--------------------------------------------\n");
             $this->sendToClient(\Man\Core\Master::NAME . ' version:' . \Man\Core\Master::VERSION . "\n");
             $this->sendToClient('start time:' . date('Y-m-d H:i:s', $status['start_time']) . '   run ' . floor((time() - $status['start_time']) / (24 * 60 * 60)) . ' days ' . floor((time() - $status['start_time']) % (24 * 60 * 60) / (60 * 60)) . " hours   \n");
             $this->sendToClient('load average: ' . implode(", ", $loadavg) . "\n");
             $this->sendToClient(count($this->connections) . ' users          ' . count($worker_pids) . ' workers       ' . count($pid_worker_name_map) . " processes\n");
             $this->sendToClient(str_pad('worker_name', $this->maxWorkerNameLength) . " exit_status     exit_count\n");
             foreach ($worker_pids as $worker_name => $pid_array) {
                 if (isset($status['worker_exit_code'][$worker_name])) {
                     foreach ($status['worker_exit_code'][$worker_name] as $exit_status => $exit_count) {
                         $this->sendToClient(str_pad($worker_name, $this->maxWorkerNameLength) . " " . str_pad($exit_status, 16) . " {$exit_count}\n");
                     }
                 } else {
                     $this->sendToClient(str_pad($worker_name, $this->maxWorkerNameLength) . " " . str_pad(0, 16) . " 0\n");
                 }
             }
             $this->sendToClient("---------------------------------------PROCESS STATUS-------------------------------------------\n");
             $this->sendToClient("pid\tmemory  " . str_pad('    listening', $this->maxAddressLength) . " timestamp  " . str_pad('worker_name', $this->maxWorkerNameLength) . " " . str_pad('total_request', 13) . " " . str_pad('packet_err', 10) . " " . str_pad('thunder_herd', 12) . " " . str_pad('client_close', 12) . " " . str_pad('send_fail', 9) . " " . str_pad('throw_exception', 15) . " suc/total\n");
             if (!\Man\Core\Master::getQueueId()) {
                 return;
             }
             $time_start = time();
             unset($pid_worker_name_map[posix_getpid()]);
             $total_worker_count = count($pid_worker_name_map);
             foreach ($pid_worker_name_map as $pid => $worker_name) {
                 posix_kill($pid, SIGUSR1);
                 if ($this->getStatusFromQueue()) {
                     $total_worker_count--;
                 }
             }
             while ($total_worker_count > 0) {
                 if ($this->getStatusFromQueue()) {
                     $total_worker_count--;
                 }
                 if (time() - $time_start > 1) {
                     break;
                 }
             }
             break;
             // 停止server
         // 停止server
         case 'stop':
             if ($master_pid) {
                 $this->sendToClient("stoping....\n");
                 posix_kill($master_pid, SIGINT);
             } else {
                 $this->sendToClient("Can not get master pid\n");
             }
             break;
             // 平滑重启server
         // 平滑重启server
         case 'reload':
             $pid_worker_name_map = $this->getPidWorkerMap();
             unset($pid_worker_name_map[posix_getpid()]);
             if ($pid_worker_name_map) {
                 foreach ($pid_worker_name_map as $pid => $item) {
                     posix_kill($pid, SIGHUP);
                 }
                 $this->sendToClient("Restart Workers\n");
             } else {
                 if ($master_pid) {
                     posix_kill($master_pid, SIGHUP);
                     $this->sendToClient("Restart Workers\n");
                 } else {
                     $this->sendToClient("Can not get master pid\n");
                 }
             }
             break;
             // admin管理员退出
         // admin管理员退出
         case 'quit':
             $this->sendToClient("Admin Quit\n");
             $this->closeClient($this->currentDealFd);
             break;
         case '':
             break;
         default:
             $this->sendToClient("Unkonw CMD \nAvailable CMD:\n status     show server status\n stop       stop server\n reload     graceful restart server\n quit       quit and close connection\n kill pid   kill the worker process of the pid\n");
     }
 }
예제 #2
0
 /**
  * 根据配置文件创建Workers
  * @return void
  */
 protected static function spawnWorkers()
 {
     // 生成一定量的worker进程
     foreach (Config::getAllWorkers() as $worker_name => $config) {
         // 初始化
         if (empty(self::$workerPidMap[$worker_name])) {
             self::$workerPidMap[$worker_name] = array();
         }
         while (count(self::$workerPidMap[$worker_name]) < $config['start_workers']) {
             // 子进程退出
             if (self::createOneWorker($worker_name) == 0) {
                 self::notice("Worker exit unexpected");
                 exit(500);
             }
         }
     }
 }