예제 #1
0
 /**
  * 进程启动时初始化
  * @see Man\Core.SocketWorker::onStart()
  */
 protected function onStart()
 {
     // 定时检查与gateway进程的连接
     \Man\Core\Lib\Task::init($this->event);
     \Man\Core\Lib\Task::add(1, array($this, 'checkGatewayConnections'));
     $this->checkGatewayConnections();
     Gateway::setBusinessWorker($this);
 }
예제 #2
0
 public function onStart()
 {
     // 初始化定时任务,让$this->event负责定时触发
     \Man\Core\Lib\Task::init($this->event);
     // 定时任务1的时间间隔2秒
     $time_interval1 = 2;
     // 设定定时任务
     \Man\Core\Lib\Task::add($time_interval1, function () {
         // 任务逻辑
         //echo 11 . PHP_EOL;
     });
     // 定时任务2的时间间隔10秒
     $time_interval2 = 10;
     // 设定定时任务,定时运行 $this->dealProcess();
     \Man\Core\Lib\Task::add($time_interval2, array($this, 'taskTwo'));
 }
예제 #3
0
 /**
  * 该worker进程开始服务的时候会触发一次
  * @return bool
  */
 public function start()
 {
     if (\Man\Core\Lib\Config::get('workerman.debug') != 1 || !\Man\Core\Master::getQueueId()) {
         while (1) {
             if (!$this->hasShutDown()) {
                 sleep(PHP_INT_MAX);
             } else {
                 exit(0);
             }
         }
     }
     $msg_type = $message = 0;
     \Man\Core\Lib\Task::init();
     \Man\Core\Lib\Task::add(1, array($this, 'sendSignalAndGetResult'));
     \Man\Core\Lib\Task::add(1, array($this, 'checkFilesModify'));
     \Man\Core\Lib\Task::add(1, array($this, 'checkTty'));
     while (1) {
         $this->collectFiles(true);
         if ($this->hasShutDown()) {
             exit(0);
         }
     }
     return true;
 }
예제 #4
0
 /**
  * 该进程开始服务
  * @see SocketWorker::start()
  */
 public function start()
 {
     // 安装信号
     $this->installSignal();
     // 初始化任务
     \Man\Core\Lib\Task::init($this->event);
     \Man\Core\Lib\Task::add(self::CLEAR_LOGS_TIME_LONG, array($this, 'clearLogs'), array(WORKERMAN_LOG_DIR));
     \Man\Core\Lib\Task::add(self::CHECK_MASTER_PROCESS_TIME_LONG, array($this, 'checkMasterProcess'));
     \Man\Core\Lib\Task::add(self::CHECK_MASTER_STATUS_TIME_LONG, array($this, 'checkMasterStatus'));
     \Man\Core\Lib\Task::add(self::CHECK_MASTER_STATUS_TIME_LONG, array($this, 'checkMemUsage'));
     // 添加accept事件
     $this->event->add($this->mainSocket, \Man\Core\Events\BaseEvent::EV_READ, array($this, 'onAccept'));
     // 主体循环
     $ret = $this->event->loop();
 }
예제 #5
0
 /**
  * 服务运行
  * @return void
  */
 public static function run()
 {
     // 输出信息
     self::notice("Workerman is starting ...", true);
     // 初始化
     self::init();
     // 检查环境
     self::checkEnv();
     // 变成守护进程
     self::daemonize();
     // 保存进程pid
     self::savePid();
     // 安装信号
     self::installSignal();
     // 创建监听套接字
     self::createListeningSockets();
     // 创建worker进程
     self::spawnWorkers();
     // 输出信息
     self::notice("\nWorkerman start success ...", true);
     // 标记服务状态为运行中
     self::$serviceStatus = self::STATUS_RUNNING;
     // 初始化任务
     \Man\Core\Lib\Task::init();
     // 关闭标准输出
     self::resetStdFd();
     // 主循环
     self::loop();
 }
예제 #6
0
 /**
  * 初始化
  * 统计目录检查
  * 初始化任务
  * @see Man\Core.SocketWorker::onStart()
  */
 protected function onStart()
 {
     // 初始化目录
     umask(0);
     $statistic_dir = WORKERMAN_LOG_DIR . $this->statisticDir;
     if (!is_dir($statistic_dir)) {
         mkdir($statistic_dir, 0777, true);
     }
     $log_dir = WORKERMAN_LOG_DIR . $this->logDir;
     if (!is_dir($log_dir)) {
         mkdir($log_dir, 0777, true);
     }
     // 初始化任务
     \Man\Core\Lib\Task::init($this->event);
     // 定时保存统计数据
     \Man\Core\Lib\Task::add(self::WRITE_PERIOD_LENGTH, array($this, 'writeStatisticsToDisk'));
     \Man\Core\Lib\Task::add(self::WRITE_PERIOD_LENGTH, array($this, 'writeLogToDisk'));
     // 定时清理不用的统计数据
     \Man\Core\Lib\Task::add(self::CLEAR_PERIOD_LENGTH, array($this, 'clearDisk'), array(WORKERMAN_LOG_DIR . $this->statisticDir, self::EXPIRED_TIME));
     \Man\Core\Lib\Task::add(self::CLEAR_PERIOD_LENGTH, array($this, 'clearDisk'), array(WORKERMAN_LOG_DIR . $this->logDir, self::EXPIRED_TIME));
 }
예제 #7
0
 /**
  * 进程启动
  */
 public function start()
 {
     // 安装信号处理函数
     $this->installSignal();
     // 添加accept事件
     $ret = $this->event->add($this->mainSocket, Man\Core\Events\BaseEvent::EV_READ, array($this, 'accept'));
     // 创建内部通信套接字,用于与BusinessWorker通讯
     $start_port = Man\Core\Lib\Config::get($this->workerName . '.lan_port_start');
     // 计算本进程监听的ip端口
     if (strpos(\Man\Core\Master::VERSION, 'mt')) {
         $this->lanPort = $start_port + \Thread::getCurrentThreadId() % 100;
     } else {
         $this->lanPort = $start_port - posix_getppid() + posix_getpid();
     }
     // 如果端口不在合法范围
     if ($this->lanPort < 0 || $this->lanPort >= 65535) {
         $this->lanPort = rand($start_port, 65535);
     }
     // 如果
     $this->lanIp = Man\Core\Lib\Config::get($this->workerName . '.lan_ip');
     if (!$this->lanIp) {
         $this->notice($this->workerName . '.lan_ip not set');
         $this->lanIp = '127.0.0.1';
     }
     $error_no_udp = $error_no_tcp = 0;
     $error_msg_udp = $error_msg_tcp = '';
     // 执行监听
     $this->innerMainSocketUdp = stream_socket_server("udp://" . $this->lanIp . ':' . $this->lanPort, $error_no_udp, $error_msg_udp, STREAM_SERVER_BIND);
     $this->innerMainSocketTcp = stream_socket_server("tcp://" . $this->lanIp . ':' . $this->lanPort, $error_no_tcp, $error_msg_tcp, STREAM_SERVER_BIND | STREAM_SERVER_LISTEN);
     // 出错,退出,下次会换个端口
     if (!$this->innerMainSocketUdp || !$this->innerMainSocketTcp) {
         $this->notice('create innerMainSocket udp or tcp fail and exit ' . $error_msg_udp . $error_msg_tcp);
         $this->stop();
     } else {
         stream_set_blocking($this->innerMainSocketUdp, 0);
         stream_set_blocking($this->innerMainSocketTcp, 0);
     }
     // 注册套接字
     if (!$this->registerAddress($this->lanIp . ':' . $this->lanPort)) {
         $this->notice('registerAddress fail and exit');
         $this->stop();
     }
     // 添加读udp/tcp事件
     $this->event->add($this->innerMainSocketUdp, Man\Core\Events\BaseEvent::EV_READ, array($this, 'recvInnerUdp'));
     $this->event->add($this->innerMainSocketTcp, Man\Core\Events\BaseEvent::EV_READ, array($this, 'acceptInnerTcp'));
     // 初始化心跳包时间间隔
     $ping_interval = \Man\Core\Lib\Config::get($this->workerName . '.ping_interval');
     if ((int) $ping_interval > 0) {
         $this->pingInterval = (int) $ping_interval;
     }
     // 获取心跳包数据
     $ping_data_or_path = \Man\Core\Lib\Config::get($this->workerName . '.ping_data');
     if (is_file($ping_data_or_path)) {
         $this->pingData = file_get_contents($ping_data_or_path);
     } else {
         $this->pingData = $ping_data_or_path;
     }
     // 不返回心跳回应(客户端发来的任何数据都算是回应)的限定值
     $this->pingNotResponseLimit = (int) \Man\Core\Lib\Config::get($this->workerName . '.ping_not_response_limit');
     // 设置定时任务,发送心跳
     if ($this->pingInterval > 0) {
         \Man\Core\Lib\Task::init($this->event);
         \Man\Core\Lib\Task::add($this->pingInterval, array($this, 'ping'));
     }
     // 主体循环,整个子进程会阻塞在这个函数上
     $ret = $this->event->loop();
     // 下面正常不会执行到
     $this->notice('worker loop exit');
     // 执行到就退出
     exit(0);
 }
예제 #8
0
 /**
  * 事件轮训库主循环
  * @see \Man\Core\Events\BaseEvent::loop()
  */
 public function loop()
 {
     $e = null;
     while (1) {
         $read = $this->readFds;
         //usleep(200000);
         $write = $this->writeFds;
         // stream_select false:出错 0:超时
         if (!($ret = @stream_select($read, $write, $e, 1))) {
             // 超时
             if ($ret === 0) {
                 \Man\Core\Lib\Task::tick();
             } elseif ($ret === false) {
             }
             // 触发信号处理函数
             continue;
         }
         // 检查所有可读描述符
         foreach ($read as $fd) {
             $fd_key = (int) $fd;
             if (isset($this->allEvents[$fd_key][self::EV_READ])) {
                 call_user_func_array($this->allEvents[$fd_key][self::EV_READ]['func'], array($this->allEvents[$fd_key][self::EV_READ]['fd'], self::EV_READ, $this->allEvents[$fd_key][self::EV_READ]['args']));
             }
         }
         // 检查可写描述符,没用到,暂不实现
         if ($write) {
             foreach ($write as $fd) {
                 $fd_key = (int) $fd;
                 if (isset($this->allEvents[$fd_key][self::EV_WRITE])) {
                     call_user_func_array($this->allEvents[$fd_key][self::EV_WRITE]['func'], array($this->allEvents[$fd_key][self::EV_WRITE]['fd'], self::EV_WRITE, $this->allEvents[$fd_key][self::EV_WRITE]['args']));
                 }
             }
         }
     }
 }
예제 #9
0
 /**
  * 停止服务
  * @return void
  */
 public static function stop()
 {
     // 如果没有子进程则直接退出
     $all_worker_pid = self::getPidWorkerNameMap();
     if (empty($all_worker_pid)) {
         exit(0);
     }
     // 标记server开始关闭
     self::$serviceStatus = self::STATUS_SHUTDOWN;
     // killWorkerTimeLong 秒后如果还没停止则强制杀死所有进程
     Task::add(self::KILL_WORKER_TIME_LONG, array('\\Man\\Core\\Master', 'stopAllWorker'), array(true), false);
     // 停止所有worker
     self::stopAllWorker();
 }
예제 #10
0
 /**
  * 停止服务
  * @return void
  */
 public function stop($force = false)
 {
     // 触发该worker进程onStop事件
     $this->onStop();
     // 强制退出
     if ($force) {
         $this->workerStatus = self::STATUS_SHUTDOWN;
         exit(0);
     }
     // 标记这个worker开始停止服务
     if ($this->workerStatus != self::STATUS_SHUTDOWN) {
         // 停止接收连接
         if ($this->mainSocket) {
             $this->event->del($this->mainSocket, BaseEvent::EV_READ);
             fclose($this->mainSocket);
         }
         $this->workerStatus = self::STATUS_SHUTDOWN;
     }
     // 没有链接要处理了
     if ($this->allTaskHasDone()) {
         exit(0);
     }
     // EXIT_WAIT_TIME秒后退出进程
     Task::add(self::EXIT_WAIT_TIME, function () {
         exit(0);
     });
 }