在使用 hyperf 之前需要了解的幾個知識點
進程,線程,協程區別
- 進程是具有一定獨立功能的程序關於某個數據集合上的一次運行活動,進程是系統進行資源分配和調度的一個獨立單位。上下文進程間的切換開銷比較大
- 線程是進程的一個實體,是CPU調度和分派的基本單位,它是比進程更小的能獨立運行的基本單位,線程間通信主要通過共享內存,上下文切換很快,資源開銷較少,但相比進程不夠穩定容易丟失數據。
- 協程是一種用戶態的輕量級線程,協程的調度完全由用戶控制。所以上下文的切換非常快。
線程進程都是同步機制,而協程則是異步
協程與線程主要區別是它將不再被內核調度,協程是用戶程序控制,線程是將自己交給內核調度
swoole 生命週期
當一個請求到來,會由某個Reactor線程發生了連接,然後告訴Master進程,Master進程告訴Manager進程,由Manage進程負責分配給Worker進程和Task進程,最後將返回結果告訴Reactor進程發送給客戶端
swoole中的角色有以下四種
Reactor線程:
- 負責維護客戶端連接,處理網絡IO、處理協議、收發數據。
- 完全是異步非阻塞的模式
- 以多線程的方式運行
Master進程:
- 分配請求到 Reactor線程
- 通知 Manager進程分配任務
Manager進程:
- fork 出Work和Task進程,回收子進程
Worker進程:
- 負責業務處理邏輯,可以異步也可以同步模式
- 多進程的方式運行
- 與Reactor交互,接受數據並處理返回給Reactor
Task進程:
- 執行異步業務
- 同步阻塞模式
- 以多進程的方式運行
hyperf 容器內的類都是單例
避免協程間數據混淆
在傳統的 PHP-FPM 的框架裏,會習慣提供一個 AbstractController 或其它命名的 Controller 抽象父類,然後定義的 Controller 需要繼承它用於獲取一些請求數據或進行一些返回操作,但是因爲Hyperf 內絕大部分的對象包括 Controller 都是以 單例(Singleton) 形式存在的,所以在編寫代碼時請務必注意 不要 將單個請求相關的數據儲存在類屬性內,包括非靜態屬性。,我們可以注意到我們獲取 請求(Request) 與 響應(Response) 對象時是通過注入 Hyperf\HttpServer\Contract\RequestInterface 和 Hyperf\HttpServer\Contract\ResponseInterface 來獲取的,
hyperf中的進程,線程,協程
我們可以在Shell裏運行,使用pstree查看進程模型結構:
reactor_num:表示Master進程中,Reactor線程總共開多少個,注意,這個可不是越多越好,因爲計算機的CPU是有限的,所以一般設置爲與CPU核心數量相同,或者兩倍即可。
worker_num:表示啓動多少個Worker進程,同樣,Worker進程數量不是越多越好,仍然設置爲與CPU核心數量相同,或者兩倍即可。
task_worker_num :Task進程是同步阻塞的,配置方式與Worker同步模式一致
swoole中線程和協程的關係
Swoole的協程在底層實現上是單線程的,因此同一時間只有一個協程在工作,協程的執行是串行的。這與線程不同,多個線程會被操作系統調度到多個CPU並行執行。
一個協程正在運行時,其他協程會停止工作。當前協程執行阻塞IO操作時會掛起,底層調度器會進入事件循環。當有IO完成事件時,底層調度器恢復事件對應的協程的執行。
對CPU多核的利用,仍然依賴於Swoole引擎的多進程機制。
一個協程正在運行時,其他協程會停止工作 意思是一個 cpu 核心上, 只能運行一個協程麼? 同一時刻, 線程一個 cpu 核心上也只能運行一個線程呀? 區別是協程會執行完自己讓出 cpu, 線程是讓 cpu 自動調度麼?
對CPU多核的利用,仍然依賴於Swoole引擎的多進程機制 意思是請求分發到不同的 worker 進程上, worker 進程被調度到不同的 cpu 核心, 每個 cpu 核心當前都是可以執行一個協程的, 從而達到並行執行多個協程的效果?