/** * 进程启动时初始化 * @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); }
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')); }
/** * 该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; }
/** * 该进程开始服务 * @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(); }
/** * 服务运行 * @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("[1A\n[KWorkerman start success ...[0m", true); // 标记服务状态为运行中 self::$serviceStatus = self::STATUS_RUNNING; // 初始化任务 \Man\Core\Lib\Task::init(); // 关闭标准输出 self::resetStdFd(); // 主循环 self::loop(); }
/** * 初始化 * 统计目录检查 * 初始化任务 * @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)); }
/** * 进程启动 */ 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); }
/** * 事件轮训库主循环 * @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'])); } } } } }
/** * 停止服务 * @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(); }
/** * 停止服务 * @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); }); }