基本上,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命令,實際上是給已經運行的主進程發送相關信號。