The following column workerman tutorial will introduce you to the startup process of workerman source code analysis. I hope it will be helpful to friends in need!
#workerman
Version: 3.1.8 (linux) Model: GatewayWorker (the Worker model can be compared with it)Note: Only part of the code to explain is posted, and the source is given in the form of a file name. You can check it out by yourselfworkerman initially only developed the Linux version, win was added later, and is run based on the command line mode (cli).Multi-process model
Worker process, Master, Gateway and Worker, Gateway is mainly used to process IO events and save client connection status. Send data processing requests to Worker and other tasks. Worker is a complete business logic processing. The former is IO-intensive and the latter is computing-intensive. They communicate through the network. Gateway and Worker register communication addresses in pairs, so It is very convenient for distributed deployment. If the business processing volume is large, you can simply add Worker services. They have a parent process (Master) responsible for monitoring, monitoring the status of the child process, sending signals to the child process, and accepting commands and signals from the terminal. The parent process can be said to be the entry point after the entire system is started.Start command parsing
Since it is running in command mode (cli) (note the difference with fpm, which handles requests from the web page) , there must be a startup script parsing command. For example, version 3.x (previously the default was daemon) adds a -d parameter to indicate that the daemon process is running. When parsed to this parameter, set self::$daemon = true, and then fork The child process can leave the current process group, set the process group leader, etc. There are two very important parameters $argc and $argc. The former represents the number of parameters, and the latter is an array that saves all the parameters of the command, such as: sudo php start.php start -d, $argv is array([0]=>start.php, [1]=>start, [2]=>-d), and $argv is mainly used for parsing. Startup mainly performs the following steps: 1. Include the automatic loader Autoloader and load the startup files under each Application; 2. Set the _appInitPath root directory; 3. Parse, initialize parameters, and execute corresponding commands. The following is the specific implementation (workerman/worker.php):public static function parseCommand() { // 检查运行命令的参数 global $argv; $start_file = $argv[0]; // 命令 $command = trim($argv[1]); // 子命令,目前只支持-d $command2 = isset($argv[2]) ? $argv[2] : ''; // 检查主进程是否在运行 $master_pid = @file_get_contents(self::$pidFile); $master_is_alive = $master_pid && @posix_kill($master_pid, 0); if($master_is_alive) { if($command === 'start') { self::log("Workerman[$start_file] is running"); } } elseif($command !== 'start' && $command !== 'restart') { self::log("Workerman[$start_file] not run"); } // 根据命令做相应处理 switch($command) { // 启动 workerman case 'start': if($command2 === '-d') { Worker::$daemonize = true; } break; // 显示 workerman 运行状态 case 'status': exit(0); // 重启 workerman case 'restart': // 停止 workeran case 'stop': // 想主进程发送SIGINT信号,主进程会向所有子进程发送SIGINT信号 $master_pid && posix_kill($master_pid, SIGINT); // 如果 $timeout 秒后主进程没有退出则展示失败界面 $timeout = 5; $start_time = time(); while(1) { // 检查主进程是否存活 $master_is_alive = $master_pid && posix_kill($master_pid, 0); if($master_is_alive) { // 检查是否超过$timeout时间 if(time() - $start_time >= $timeout) { self::log("Workerman[$start_file] stop fail"); exit; } usleep(10000); continue; } self::log("Workerman[$start_file] stop success"); // 是restart命令 if($command === 'stop') { exit(0); } // -d 说明是以守护进程的方式启动 if($command2 === '-d') { Worker::$daemonize = true; } break; } break; // 平滑重启 workerman case 'reload': exit; } }
Worker::runAll()
#php’s socket programming is actually similar to C. The latter re-wraps the socket and provides The interface is provided to PHP, and the steps of network programming under PHP are greatly reduced. For example: stream_socket_server and stream_socket_client directly create server/client socket (php has two sets of socket operation functions). wm makes extensive use of the former. The startup process is as follows (the comments are very detailed):public static function runAll() { // 初始化环境变量 self::init(); // 解析命令 self::parseCommand(); // 尝试以守护进程模式运行 self::daemonize(); // 初始化所有worker实例,主要是监听端口 self::initWorkers(); // 初始化所有信号处理函数 self::installSignal(); // 保存主进程pid self::saveMasterPid(); // 创建子进程(worker进程)并运行 self::forkWorkers(); // 展示启动界面 self::displayUI(); // 尝试重定向标准输入输出 self::resetStd(); // 监控所有子进程(worker进程) self::monitorWorkers(); }
6. Save the main process PID. When the system is running, we can check the system status in the terminal or execute shutdown or restart commands. Communication is through the main process, so we need to know the main process PID. We know to type one in the terminal. The executable command actually creates a new sub-process under the current terminal for execution, so we need to know the main process PID to send SIGNAL to the WM main process. At this time, the signal processing function captures the signal and executes it through a callback.
7. Create a child process and set the current process user (root). In the multi-process model, two types of sub-processes listen to different server addresses respectively. In the main process, we only create servers and do not set up listening, nor do we generate a specified number of servers.
The reason is that if we create the same socket multiple times in a process, an error will be reported. The number of workers is actually the number of sockets, that is, the number of child processes of the socket. The child process inherits the parent process context, but only listens Specific socket events;
8. In the child process, register the server socket to listen for events, and use an extended Event to achieve IO reuse, register data reading callbacks, and also register socket connections. Event callback;
9. Input and output redirection;
10. The main process monitors the status of the sub-process and calls the pcntl_signal_dispatch() function in an infinite loop to capture the exit status of the sub-process. This function will block until a child process exits;
For more workerman related knowledge, please pay attention to the workerman tutorial column.
The above is the detailed content of Detailed explanation of the startup process of workerman source code analysis. For more information, please follow other related articles on the PHP Chinese website!