基本上,workerman使用多进程的方式、使用libevent事件监听网络链接,达到高并发。它与nginx的进程模型类似,链接的处理,是由子进程完成的,主进程主要的工做是:
php
监听端口,生成子进程要共享的server_socketnginx
监听传递给本身的信号,如reload restart等,并进行相应处理网络
监听子进程退出的事件,并及启动新的子进程补上并发
master进程(master进程会先创建好须要listen的socket)--------fork生成子进程workers,继承socket(此时workers子进程们都继承了父进程master的全部属性,固然也包括已经创建好的socket,固然不是同一个socket,只是每一个进程的这个socket会监控在同一个ip地址与端口的网络事件,这个在网络协议里面是容许的)------当一个链接进入,产生惊群现象。socket
workerman中对惊群事件没有特殊处理,只是简单地忽略掉它了,这个对性能影响也很小,对业务更没有影响。函数
使用多个子进程,就能够充分利用多个cpu,并显著提升并发链接和处理能力。高并发
一,主进程的挂起原理性能
主进程监听好端口,生成子进程后,自身就处于挂起状态,只处理两件事件:监听信号、监听是否有子进程退出,实现代码见Worker::monitorWorkers方法spa
while(1) { pcntl_signal_dispatch(); // 挂起进程,直到有子进程退出或者被信号打断 $status = 0; $pid = pcntl_wait($status, WUNTRACED); // 若是有信号到来,尝试触发信号处理函数 pcntl_signal_dispatch(); if($pid > 0){ //若是有子进程退出 则尝试fork一个子进程 }else{ //说明收到了信号 } }
让进程挂起的关键就是调用pcntl_wait函数,它会一直等待、直到收到信号或有子进程退出时返回,返回值就是退出的子进程pidrest
pcntl_wait第二个参数可设为:
WNOHANG 没有子进程退出时,当即返回,显然它不能挂起进程
WUNTRACED 子进程已经退出时,当即返回,这才是实现进程挂起的关键。
正由于主进程一直是挂起状态,因此它并不消耗系统资源。
咱们调用stop|restart|reload|status|kill命令,实际上是给已经运行的主进程发送相关信号。