public function onStart() { $listen = \Man\Core\Lib\Config::get($this->workerName . '.listen'); $udp_address = str_replace('tcp', 'udp', $listen); $this->broadcastSocket = stream_socket_server($udp_address, $error_no, $error_msg, STREAM_SERVER_BIND); $this->event->add($this->broadcastSocket, \Man\Core\Events\BaseEvent::EV_READ, array($this, 'dealBroadcastUdp')); }
/** * 启动的时候初始化统计上报地址) * @see Man\Core.SocketWorker::onStart() */ public function onStart() { // 获取统计上报地址 $statistic_address = \Man\Core\Lib\Config::get($this->workerName . '.statistic_address'); if ($statistic_address) { $this->statisticAddress = $statistic_address; } }
/** * 进程启动时做的一些初始化工作 * @see Man\Core.SocketWorker::onStart() * @return void */ public function onStart() { // 查看配置中是否有设置Protocol if ($protocol = \Man\Core\Lib\Config::get($this->workerName . '.thrift_protocol')) { $this->thriftProtocol = "\\Thrift\\Protocol\\" . $protocol; if (!class_exists($this->thriftProtocol, true)) { $this->notice('Class ' . $this->thriftProtocol . ' not exsits , Please check ./conf/conf.d/' . $this->workerName . '.conf'); return; } } // 查看配置中是否有设置Transport if ($transport = \Man\Core\Lib\Config::get($this->workerName . '.thrift_transport')) { $this->thriftTransport = "\\Thrift\\Transport\\" . $transport; if (!class_exists($this->thriftTransport, true)) { $this->notice('Class ' . $this->thriftTransport . ' not exsits , Please check ./conf/conf.d/' . $this->workerName . '.conf'); return; } } // 载入该服务下的所有文件 foreach (glob(THRIFT_ROOT . '/Services/' . $this->workerName . '/*.php') as $php_file) { require_once $php_file; } // 检查类是否存在 $processor_class_name = "\\Services\\" . $this->workerName . "\\" . $this->workerName . 'Processor'; if (!class_exists($processor_class_name)) { $this->notice("Class {$processor_class_name} not found"); return; } // 检查类是否存在 $handler_class_name = "\\Services\\" . $this->workerName . "\\" . $this->workerName . 'Handler'; if (!class_exists($handler_class_name)) { $this->notice("Class {$handler_class_name} not found"); return; } // 统计上报地址 $statistic_address = \Man\Core\Lib\Config::get($this->workerName . '.statistic_address'); if ($statistic_address) { $this->statisticAddress = $statistic_address; } $handler = new $handler_class_name(); $this->processor = new $processor_class_name($handler); }
/** * 运行线程 */ public function run() { date_default_timezone_set('Asia/Shanghai'); // 保存一个副本 $this->mainSocket = $this->worker->mainSocket; // 改变当前工作目录 chdir(WORKERMAN_ROOT_DIR); // 重新载入一次配置 \Man\Core\Lib\Config::reload(); // 载入入口文件 require_once $this->worker->workerFile; // 入口文件类名 $class_name = basename($this->worker->workerFile, '.php'); // 实例化入口类 $worker = new $class_name($this->worker->serviceName); // 如果该worker有配置监听端口,则将监听端口的socket传递给子进程 if ($this->mainSocket) { $worker->setListendSocket($this->mainSocket); } // 使worker开始服务 $worker->start(); }
/** * 该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; }
/** * 检查worker配置、worker语法错误等 * @return void */ public static function checkWorkersConfig() { $current_pwuid = posix_getpwuid(posix_getuid()); $current_user_name = $current_pwuid['name']; self::$maxUserNameLength = strlen($current_user_name); foreach (Config::getAllWorkers() as $worker_name => $config) { if (strlen($worker_name) > self::$maxWorkerNameLength) { self::$maxWorkerNameLength = strlen($worker_name); } if (isset($config['user']) && strlen($config['user']) > self::$maxUserNameLength) { self::$maxUserNameLength = strlen($config['user']); } if (isset($config['listen']) && strlen($config['listen']) > self::$maxListenLength) { self::$maxListenLength = strlen($config['listen']); } } $total_worker_count = 0; // 检查worker 是否有语法错误 echo "------------------------[47;30m WORKERS [0m-------------------------------\n"; echo "[47;30muser[0m", str_pad('', self::$maxUserNameLength + 2 - strlen('user')), "[47;30mworker[0m", str_pad('', self::$maxWorkerNameLength + 2 - strlen('worker')), "[47;30mlisten[0m", str_pad('', self::$maxListenLength + 2 - strlen('listen')), "[47;30mprocesses[0m", str_pad('', self::$maxProcessCountLength + 2 - strlen('processes')), "[47;30m", "status[0m\n"; foreach (Config::getAllWorkers() as $worker_name => $config) { if (isset($config['user'])) { $worker_user = $config['user']; if (!self::checkWorkerUserName($worker_user)) { echo str_pad($config['user'], self::$maxUserNameLength + 2), str_pad($worker_name, self::$maxWorkerNameLength + 2), "[31;40m [FAIL] [0m\n"; \Man\Core\Master::notice("Can not run {$worker_name} processes as user {$worker_user} , User {$worker_user} not exists\tWorkerman start fail"); exit("\n[31;40mCan not run {$worker_name} processes as user {$worker_user} , User {$worker_user} not exists[0m\n\n[31;40mWorkerman start fail[0m\n\n"); } } else { $worker_user = $current_user_name; } echo str_pad($worker_user, self::$maxUserNameLength + 2), str_pad($worker_name, self::$maxWorkerNameLength + 2); if (isset($config['listen'])) { echo str_pad($config['listen'], self::$maxListenLength + 2); } else { echo str_pad('none', self::$maxListenLength + 2); } if (empty($config['start_workers'])) { \Man\Core\Master::notice(str_pad($worker_name, 40) . " [start_workers not set]\tWorkerman start fail"); exit(str_pad('', self::$maxProcessCountLength + 2) . "[31;40m [start_workers not set][0m\n\n[31;40mWorkerman start fail[0m\n"); } echo str_pad(' ' . $config['start_workers'], self::$maxProcessCountLength + 2); $total_worker_count += $config['start_workers']; // 语法检查 if ($worker_file = \Man\Core\Lib\Config::get($worker_name . '.worker_file')) { $class_name = basename($worker_file, '.php'); } else { \Man\Core\Master::notice("{$worker_name} not set worker_file in conf/conf.d/{$worker_name}.conf"); echo "[31;40m [not set worker_file] [0m\n"; continue; } if (0 != self::checkSyntaxError($worker_file, $class_name)) { //unset(Config::instance()->config[$worker_name]); \Man\Core\Master::notice("{$worker_name} has Fatal Err"); echo "[31;40m [Fatal Err] [0m\n"; continue; } echo "[32;40m [OK] [0m\n"; } if ($total_worker_count > \Man\Core\Master::SERVER_MAX_WORKER_COUNT) { \Man\Core\Master::notice("Number of worker processes can not be greater than " . \Man\Core\Master::SERVER_MAX_WORKER_COUNT . ".\tPlease check start_workers in " . WORKERMAN_ROOT_DIR . "config/main.php\tWorkerman start fail"); exit("\n[31;40mNumber of worker processes can not be greater than " . \Man\Core\Master::SERVER_MAX_WORKER_COUNT . ".\nPlease check start_workers in " . WORKERMAN_ROOT_DIR . "config/main.php[0m\n\n[31;40mWorkerman start fail[0m\n"); } echo "----------------------------------------------------------------\n"; }
/** * 进程启动 */ 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); }
protected function getExcludeFiles() { $exclude_path = \Man\Core\Lib\Config::get($this->workerName . '.exclude_path'); return (array) $exclude_path; }
/** * 设置server信号处理函数 * @param null $null * @param int $signal */ public function signalHandler($signal, $null = null, $null = null) { switch ($signal) { // 时钟处理函数 case SIGALRM: // 停止服务后EXIT_WAIT_TIME秒还没退出则强制退出 if ($this->workerStatus == self::STATUS_SHUTDOWN) { exit(0); } break; // 停止该进程 // 停止该进程 case SIGINT: $this->stop(); // EXIT_WAIT_TIME秒后退出进程 pcntl_alarm(self::EXIT_WAIT_TIME); break; // 平滑重启 // 平滑重启 case SIGHUP: $this->onReload(); // 如果配置了no_reload则不重启该进程 if (\Man\Core\Lib\Config::get($this->workerName . '.no_reload')) { return; } $this->stop(); // EXIT_WAIT_TIME秒后退出进程 pcntl_alarm(self::EXIT_WAIT_TIME); break; // 报告进程状态 // 报告进程状态 case SIGUSR1: $this->writeStatusToQueue(); break; // 报告进程使用的php文件 // 报告进程使用的php文件 case SIGUSR2: $this->writeFilesListToQueue(); break; // FileMonitor检测到终端已经关闭,向此进程发送SIGTTOU信号,关闭此进程的标准输入输出 // FileMonitor检测到终端已经关闭,向此进程发送SIGTTOU信号,关闭此进程的标准输入输出 case SIGTTOU: $this->resetFd(); break; } }
/** * 创建一个worker进程 * @param string $worker_name worker的名称 * @return int 父进程:>0得到新worker的pid ;<0 出错; 子进程:始终为0 */ protected static function forkOneWorker($worker_name) { // 创建子进程 $pid = pcntl_fork(); // 先处理收到的信号 pcntl_signal_dispatch(); // 父进程 if ($pid > 0) { // 初始化master的一些东东 self::$workerPids[$worker_name][$pid] = $pid; // 更新进程信息到共享内存 self::updateStatusToShm(); return $pid; } elseif ($pid === 0) { // 忽略信号 self::ignoreSignal(); // 清空任务 Lib\Task::delAll(); // 关闭不用的监听socket foreach (self::$listenedSockets as $tmp_worker_name => $tmp_socket) { if ($tmp_worker_name != $worker_name) { fclose($tmp_socket); } } // 尝试以指定用户运行worker if ($worker_user = Lib\Config::get($worker_name . '.user')) { self::setWorkerUser($worker_user); } // 关闭输出 self::resetStdFd(); // 尝试设置子进程进程名称 self::setWorkerProcessTitle($worker_name); // 查找worker文件 if ($worker_file = \Man\Core\Lib\Config::get($worker_name . '.worker_file')) { include_once $worker_file; $class_name = basename($worker_file, '.php'); } else { $class_name = $worker_name; include_once WORKERMAN_ROOT_DIR . "workers/{$worker_name}.php"; } // 创建实例 $worker = new $class_name($worker_name); // 如果该worker有配置监听端口,则将监听端口的socket传递给子进程 if (isset(self::$listenedSockets[$worker_name])) { $worker->setListendSocket(self::$listenedSockets[$worker_name]); } // 使worker开始服务 $worker->start(); return 0; } else { self::notice("create worker fail worker_name:{$worker_name} detail:pcntl_fork fail"); return $pid; } }
/** * 获取本地ip * @param string $worker_name * @return string */ public function getIp($worker_name = '') { $ip = $this->getLocalIp(); if (empty($ip) || $ip == '0.0.0.0' || ($ip = '127.0.0.1')) { if ($worker_name) { $ip = \Man\Core\Lib\Config::get($worker_name . '.ip'); } if (empty($ip) || $ip == '0.0.0.0' || ($ip = '127.0.0.1')) { $ret_string = shell_exec('ifconfig'); if (preg_match("/:(\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3})/", $ret_string, $match)) { $ip = $match[1]; } } } return $ip; }
/** * 初始化AccessLog * @return void */ public function initAccessLog() { // 虚拟机访问日志目录 self::$accessLog = \Man\Core\Lib\Config::get($this->workerName . '.access_log'); // 默认访问日志目录 if ($default_access_log = \Man\Core\Lib\Config::get($this->workerName . '.default_access_log')) { self::$defaultAccessLog = $default_access_log; } }
/** * 检查worker配置、worker语法错误等 * @return void */ public static function checkWorkersConfig() { $pad_length = 26; $total_worker_count = 0; // 检查worker 是否有语法错误 echo "----------------------WORKERS--------------------\n"; foreach (Config::getAllWorkers() as $worker_name => $config) { if (empty($config['start_workers'])) { \Man\Core\Master::notice(str_pad($worker_name, $pad_length) . " [start_workers not set]\tServer start fail"); exit(str_pad($worker_name, $pad_length) . "[31;40m [start_workers not set][0m\n\n[31;40mServer start fail[0m\n"); } $total_worker_count += $config['start_workers']; // 语法检查 if ($worker_file = \Man\Core\Lib\Config::get($worker_name . '.worker_file')) { $class_name = basename($worker_file, '.php'); } else { $worker_file = WORKERMAN_ROOT_DIR . "workers/{$worker_name}.php"; $class_name = $worker_name; } if (0 != self::checkSyntaxError($worker_file, $class_name)) { unset(Config::instance()->config[$worker_name]); \Man\Core\Master::notice("{$worker_name} has Fatal Err"); echo str_pad($worker_name, $pad_length), "[31;40m [Fatal Err] [0m\n"; continue; } if (isset($config['user'])) { $worker_user = $config['user']; if (!self::checkWorkerUserName($worker_user)) { echo str_pad($worker_name, $pad_length), "[31;40m [FAIL] [0m\n"; \Man\Core\Master::notice("Can not run {$worker_name} processes as user {$worker_user} , User {$worker_user} not exists\tServer start fail"); exit("\n[31;40mCan not run {$worker_name} processes as user {$worker_user} , User {$worker_user} not exists[0m\n\n[31;40mServer start fail[0m\n\n"); } } echo str_pad($worker_name, $pad_length), "[32;40m [OK] [0m\n"; } if ($total_worker_count > \Man\Core\Master::SERVER_MAX_WORKER_COUNT) { \Man\Core\Master::notice("Number of worker processes can not be more than " . \Man\Core\Master::SERVER_MAX_WORKER_COUNT . ".\tPlease check start_workers in " . WORKERMAN_ROOT_DIR . "config/main.php\tServer start fail"); exit("\n[31;40mNumber of worker processes can not be more than " . \Man\Core\Master::SERVER_MAX_WORKER_COUNT . ".\nPlease check start_workers in " . WORKERMAN_ROOT_DIR . "config/main.php[0m\n\n[31;40mServer start fail[0m\n"); } echo "-------------------------------------------------\n"; }
/** * 记录日志 * @param sring $str * @return void */ protected function notice($str, $display = true) { $str = 'Worker[' . get_class($this) . ':' . posix_getpid() . ']:' . $str; Log::add($str); if ($display && Config::get('workerman.debug') == 1) { echo $str . "\n"; } }
/** * 检查控制终端是否已经关闭, 如果控制终端关闭,则停止打印数据到终端 * @return void */ public static function checkTty() { // 已经重置了fd,就不检查终端是否关闭,因为不会打印东西到屏幕了 if (self::$hasResetStd) { return; } // 没开启debug不打印数据到屏幕,不检测终端是否关闭 if (!Config::get('workerman.debug')) { return; } // 检测终端是否关闭 if (!self::$terminalClosed && !@posix_ttyname(STDOUT)) { self::resetStdFd(true); // 日志 self::notice("terminal closed and reset workers fd"); // 获取所有子进程pid $all_worker_pid = self::getPidWorkerNameMap(); // 向所有子进程发送重置标准输入输出信号 foreach ($all_worker_pid as $pid => $worker_name) { // 发送SIGTTOU信号 posix_kill($pid, SIGTTOU); } // 设置标记 self::$terminalClosed = true; } }
/** * 检查worker配置、worker语法错误等 * @return void */ public static function checkWorkersConfig() { foreach (Config::getAllWorkers() as $worker_name => $config) { if (strlen($worker_name) > self::$maxWorkerNameLength) { self::$maxWorkerNameLength = strlen($worker_name); } if (isset($config['user']) && strlen($config['user']) > self::$maxUserNameLength) { self::$maxUserNameLength = strlen($config['user']); } if (isset($config['listen']) && strlen($config['listen']) > self::$maxListenLength) { self::$maxListenLength = strlen($config['listen']); } } $total_worker_count = 0; // 检查worker echo "------------------------ WORKERS -------------------------------\n"; echo "worker", str_pad('', self::$maxWorkerNameLength + 2 - strlen('worker')), "listen", str_pad('', self::$maxListenLength + 2 - strlen('listen')), "processes", str_pad('', self::$maxProcessCountLength + 2 - strlen('processes')), "", "status\n"; foreach (Config::getAllWorkers() as $worker_name => $config) { echo str_pad($worker_name, self::$maxWorkerNameLength + 2); if (isset($config['listen'])) { echo str_pad($config['listen'], self::$maxListenLength + 2); } else { echo str_pad('none', self::$maxListenLength + 2); } if (empty($config['start_workers'])) { \Man\Core\Master::notice(str_pad($worker_name, 40) . " [start_workers not set]\tWorkerman start fail"); exit(str_pad('', self::$maxProcessCountLength + 2) . " [start_workers not set]\n\nWorkerman start fail\n"); } echo str_pad(' ' . $config['start_workers'], self::$maxProcessCountLength + 2); $total_worker_count += $config['start_workers']; // 语法检查 if (!($worker_file = \Man\Core\Lib\Config::get($worker_name . '.worker_file'))) { \Man\Core\Master::notice("{$worker_name} not set worker_file in conf/conf.d/{$worker_name}.conf"); echo " [not set worker_file] \n"; continue; } echo " [OK] \n"; } if ($total_worker_count > \Man\Core\Master::SERVER_MAX_WORKER_COUNT) { \Man\Core\Master::notice("Number of worker processes can not be greater than " . \Man\Core\Master::SERVER_MAX_WORKER_COUNT . ".\tPlease check start_workers in " . WORKERMAN_ROOT_DIR . "config/main.php\tWorkerman start fail"); exit("\nNumber of worker processes can not be greater than " . \Man\Core\Master::SERVER_MAX_WORKER_COUNT . ".\nPlease check start_workers in " . WORKERMAN_ROOT_DIR . "config/main.php\n\nWorkerman start fail\n"); } echo "----------------------------------------------------------------\n"; }
/** * 那些路径不监控更新 * @return array */ protected function getExcludePaths() { $config_exclude_path = Config::get('Monitor.exclude_path'); // 被排除的路径 $exclude_path = array(); // 因为配置可能会被更改,所以每次都会重新从配置中查找排除路径 foreach ($config_exclude_path as $path) { if ($real_path = realpath($path)) { $exclude_path[] = $real_path; } } return (array) $exclude_path; }
/** * 创建一个worker进程 * @param string $worker_name 服务名 * @return int 父进程:>0得到新worker的pid ;<0 出错; 子进程:始终为0 */ protected static function createOneWorker($worker_name) { // 创建子进程 $pid = pcntl_fork(); // 先处理收到的信号 pcntl_signal_dispatch(); // 父进程 if ($pid > 0) { // 初始化master的一些东东 self::$workerPidMap[$worker_name][$pid] = $pid; // 更新进程信息到共享内存 self::updateStatusToShm(); return $pid; } elseif ($pid === 0) { // 忽略信号 self::ignoreSignal(); // 清空任务 Lib\Task::delAll(); // 关闭不用的监听socket foreach (self::$listenedSocketsArray as $tmp_worker_name => $tmp_socket) { if ($tmp_worker_name != $worker_name) { fclose($tmp_socket); } } // 尝试以指定用户运行worker进程 if ($worker_user = Lib\Config::get($worker_name . '.user')) { self::setProcUser($worker_user); } // 关闭输出 self::resetStdFd(Lib\Config::get($worker_name . '.no_debug')); // 尝试设置子进程进程名称 self::setWorkerProcTitle($worker_name); // 包含必要文件 require_once WORKERMAN_ROOT_DIR . 'Core/SocketWorker.php'; // 查找worker文件 $worker_file = \Man\Core\Lib\Config::get($worker_name . '.worker_file'); $class_name = basename($worker_file, '.php'); // 如果有语法错误 sleep 5秒 避免狂刷日志 if (\Man\Core\Lib\Checker::checkSyntaxError($worker_file, $class_name)) { sleep(5); } require_once $worker_file; // 创建实例 $worker = new $class_name($worker_name); // 如果该worker有配置监听端口,则将监听端口的socket传递给子进程 if (isset(self::$listenedSocketsArray[$worker_name])) { $worker->setListendSocket(self::$listenedSocketsArray[$worker_name]); } // 使worker开始服务 $worker->start(); return 0; } else { self::notice("create worker fail worker_name:{$worker_name} detail:pcntl_fork fail"); return $pid; } }
/** * 构造函数 * @param int $port * @param string $ip * @param string $protocol * @return void */ public function __construct($worker_name = null) { // worker name $this->workerName = $worker_name ? $worker_name : get_class($this); // 是否开启长连接 $this->isPersistentConnection = (bool) Lib\Config::get($this->workerName . '.persistent_connection'); // 最大请求数,超过这个数则安全重启,如果没有配置则使用PHP_INT_MAX $this->maxRequests = (int) Lib\Config::get($this->workerName . '.max_requests'); $this->maxRequests = $this->maxRequests <= 0 ? PHP_INT_MAX : $this->maxRequests; // 预读数据长度,长连接需要设置此项 $preread_length = (int) Lib\Config::get($this->workerName . '.preread_length'); if ($preread_length > 0) { $this->prereadLength = $preread_length; } elseif (!$this->isPersistentConnection) { $this->prereadLength = 65535; } // 接收缓冲区大小限制 if (($max_recv_buffer_size = Lib\Config::get($this->workerName . '.max_recv_buffer_size')) && $max_recv_buffer_size > 0) { $this->maxRecvBufferSize = $max_recv_buffer_size; } // 发送缓冲区大小限制 if (($max_send_buffer_size = Lib\Config::get($this->workerName . '.max_send_buffer_size')) && $max_send_buffer_size > 0) { $this->maxSendBufferSize = $max_send_buffer_size; } // worker启动时间 $this->statusInfo['start_time'] = time(); //事件轮询库 if (extension_loaded('libevent')) { $this->setEventLoopName('Libevent'); } // 检查退出状态 $this->addShutdownHook(); // 初始化事件轮询库 $this->event = new $this->eventLoopName(); }
/** * 构造函数 * @param int $port * @param string $ip * @param string $protocol * @return void */ public function __construct($worker_name = null) { // worker name $this->workerName = $worker_name ? $worker_name : get_class($this); // 是否开启长连接 $this->isPersistentConnection = (bool) Lib\Config::get($this->workerName . '.persistent_connection'); // 最大请求数,如果没有配置则使用PHP_INT_MAX $this->maxRequests = (int) Lib\Config::get($this->workerName . '.max_requests'); $this->maxRequests = $this->maxRequests <= 0 ? PHP_INT_MAX : $this->maxRequests; $preread_length = (int) Lib\Config::get($this->workerName . '.preread_length'); if ($preread_length > 0) { $this->prereadLength = $preread_length; } elseif (!$this->isPersistentConnection) { $this->prereadLength = 65535; } // worker启动时间 $this->statusInfo['start_time'] = time(); //事件轮询库 if (extension_loaded('libevent')) { $this->setEventLoopName('Libevent'); } // 检查退出状态 $this->addShutdownHook(); // 初始化事件轮询库 // $this->event = new Libevent(); // $this->event = new Select(); $this->event = new $this->eventLoopName(); }
/** * 根据配置文件创建Workers * @return void */ protected static function createWorkers() { require_once WORKERMAN_ROOT_DIR . 'Core/ThreadWorker.php'; $workers = Lib\Config::getAllWorkers(); foreach ($workers as $worker_name => $config) { $main_socket = isset(self::$listenedSockets[$worker_name]) ? self::$listenedSockets[$worker_name] : null; $worker_file = \Man\Core\Lib\Config::get($worker_name . '.worker_file'); self::$threads[$worker_name] = new \Pool($config['start_workers'], '\\Man\\Core\\Worker', array($main_socket, $worker_file, $worker_name)); for ($i = 0; $i < $config['start_workers']; $i++) { self::$threads[$worker_name]->submit(new ThreadWorker()); } } }