遵從硬體不行軟體來湊,出現了各種壓榨CPU幹活的非同步程式設計技術。程式生死,一般遵循誰生誰管,當然兒子出問題(退出),會被告知老爸。沒了爸了孩子(子程式)會被特殊程式收編。非同步程式設計,通常是想好退路,被動的給別人執行。本文只是介紹一些與swoole相關的概念性的內容。
緣起
nodejs中稱之為回撥地獄,解決這種回撥金字塔主要有以下幾種方案
- EventProxy 事件釋出訂閱模式
- BlueBird Promise方案 (基本上是將巢狀變為水平)
- Async 非同步流程控制庫
select,poll,epoll,kqueue
之類的C事件庫
- 生成器
- ES6原生有,python有,當然php也有,特點是需要顯性的使用
yield
關鍵字 - 具備現場儲存與返場的能力,讓渡控制權 (與此類似C的萬惡 goto 一樣,跳來跳去)
- ES6原生有,python有,當然php也有,特點是需要顯性的使用
非同步/同步/阻塞/非阻塞
- 異/同步 與 阻塞 非阻塞 其實是站在 不同的角度上對同一事件的描述。
- 前者側重是生產者如何拿到結果,後者則關注是消費者否可做其他的事。
白話就是,同步與非同步關注你能不能等,能等就是非同步,不能等現在立刻馬上就要則是同步。非阻塞與阻塞,則是指你當前能不能做別的。後者出現的情況,常在當前的任務有依賴條件,沒有了誰誰就不能繼續進行,因此需要阻塞。而前者,則不一樣,誰先誰後沒關係,也不關心怎麼來的,只要結果,當然這種情況下要求任務獨立無依賴。
程式
程式本身不是基本的執行單位,而是執行緒的容器
-
具有動態性,併發性,非同步性,結構性
- 獨立性 與其他程式隔離
- 結構性 擁有程式碼段,資料段,PCB(程式控制塊,包含程式的描述和控制資訊)
-
父子程式
fork()
在當前程式建立一個新程式exec()
切換子程式中的執行程式- 正常情況下,父程式會收到兩個返回值
exit
退了wait
獲取子程式的退出狀態,核心從記憶體中釋放已結束子程式的PCB父子程式,也就一個
fork
生了,因此如果是原生php fork完畢,在子程式時pid 為0 (特別是通過迴圈產生子fork程式)時,需要且必須執行exit讓子程式斷子絕孫,否則子子孫孫無窮盡也....
-
組長/會話程式
setpgid()
加入一個現有的程式組或建立一個新程式組setsid
非組長程式建立新會話,該會話程式成為新組長程式- 每個程式被建立時,它便會成為父程式在session中的一員
- session主要是針對一個tty終端建立(因此與守護程式相關,即換一個不是終端的seesionid)
- 在*unix中,組長程式不能建立會話,簡單理解就是在組長程式中,執行setsid函式會報錯
-
Linux特殊程式
- 0 排程程式,交換程式,系統程式
- 1 init 程式,核心呼叫,沒有終端限制
swoole程式元件
- Master程式
- swoole 應用的root程式,
fork
出 Reactor執行緒和Manager程式 - Reactor 是包含在 Master 程式中的多執行緒程式,處理 TCP 連線和資料收發(非同步非阻塞方式)
- swoole 應用的root程式,
- Manager程式
- Manager 程式負責 fork 並維護多個 Worker 子程式,負責回收並建立新的 Worker 子程式
- 當伺服器關閉時,Manager 將傳送訊號給所有 Worker 子程式,通知其關閉服務
- Worker程式
- 以多程式方式執行,負責接受由 Reactor 執行緒投遞的請求資料包
- 執行 PHP 回撥函式,生成響應資料併發給 Reactor 執行緒
- Task Worker程式
- 同上,但僅用於任務分發,Task Worker 負責從佇列中消費(同步阻塞方式處理)任務
swoole元件概念關係圖
swoole官方經典話術
Swoole 官方對 Reactor、Worker、Task Worker有一個形象的比喻,如果把基於 Swoole 的 Web 伺服器比作一個工廠,那麼 Reactor 就是這個工廠的銷售員,Worker 是負責生產的工人,銷售員負責接訂單,然後交給工人生產,而 Task Worker 可以理解為行政人員,負責提工人處理生產以外的雜事,比如訂盒飯、收快遞,讓工人可以安心生產。