下面由workerman使用教學專欄來介紹關於Workerman中你必須知道的幾個概念,希望對需要的朋友有幫助!
Workerman是純PHP開發的開源高效能的PHP socket 服務框架。它不是一個MVC框架,而是一個更底層更通用的socket服務框架,你可以用它來開發tcp代理、梯子代理、做遊戲伺服器、郵件伺服器、ftp伺服器。
推薦:Workerman教學
實際上Workerman類似一個PHP版本的nginx,核心也是多進程 Epoll 非阻塞IO。 Workerman每個行程能維持上萬並發連線。由於本身常住內存,不依賴Apache、nginx、php-fpm這些容器,擁有超高的效能。
同時支援TCP、UDP、UNIXSOCKET,支援長連接,支援Websocket、HTTP、WSS、HTTPS等通訊協以及各種自訂協定。擁有定時器、非同步socket客戶端、非同步Mysql、非同步Redis、非同步Http、非同步訊息佇列等眾多高效能元件。
首先需要了解幾個核心概念,1.多進程2.Epoll 3.非阻塞IO
1、多進程:
首先什麼是進程呢,一個進程包含了程式碼、資料和分配給進程的資源(記憶體),在電腦系統裡直觀地說一個進程就是一個PID。作業系統保護行程空間不受外部行程幹擾,也就是一個行程不能存取到另一個行程的記憶體。
有時候進程間需要進行通信,這時可以使用作業系統提供進程間通訊機制。通常情況下,執行一個可執行檔案作業系統會為其建立一個進程以供它運行。
但如果該執行檔是基於多進程設計的話,作業系統會在最初的進程上創建出多個進程出來,這些進程間執行的程式碼是一樣,但執行結果可能是一樣的,也可能是不一樣的。
為什麼需要多進程? 最直觀的想法是,如果作業系統支援多核心的話,那麼一個執行檔可以在不同的核心上跑;即使是非多核心的,在一個行程在等待I/O操作時另一個行程也可以在CPU上跑,提高CPU利用率、程式的效率。
在Linux系統上可以透過fork()來在父行程中建立出子程序。一個行程呼叫fork()後,系統會先給新行程分配資源,例如儲存資料和程式碼空間。然後把原來進程的所有值、狀態都複製到新的進程裡,只有少數的值與原來的進程不同,以區分不同的進程。
fork()函數會回傳兩次,一次給父行程(傳回子程序的pid或fork失敗訊息),一次給子程序(回傳0)。至此,兩個進程分道揚鑣,各自運作在系統裡。
2、非阻塞IO:
首先什麼是IO,也就是input與output的操作。網路IO的本質是socket的讀取,socket在linux系統被抽象化為流,IO可以理解為對流的操作。對於一次IO存取(以read舉例),資料會先被拷貝到作業系統核心的緩衝區中,然後才會從作業系統核心的緩衝區拷貝到應用程式的位址空間。
所以說,當一個read操作發生時,它會經歷兩個階段:
第一階段(等待資料):等待資料準備 (Waiting for the data to be ready)。
第二階段(拷貝資料):將資料從核心拷貝到進程中(Copying the data from the kernel to the process)
對於socket流(即IO)而言,
第一步:通常涉及等待網路上的資料分組到達,然後複製到核心的某個緩衝區。
第二步:把資料從核心緩衝區複製到應用程式緩衝區。
網路IO的模型大致有以下幾種:
同步模型(synchronous IO)
阻塞IO(bloking IO)資源不可用時,IO請求一直阻塞,直到回饋結果(有資料或逾時)。在linux中,預設所有的socket都是blocking,blocking IO的特點就是在IO執行的兩個階段(等待資料和拷貝資料兩個階段)都被block了。
非阻塞IO(non-blocking IO)資源不可用時,IO請求離開返回,返回資料標識資源不可用。在linux中,如果資料還沒準備好,那麼它就不會block使用者進程,核心馬上回傳給進程,說明這個指令不能立即滿足(EAGAIN 或 EWOULDBLOCK)。因此非阻塞就是使用輪詢的(polling)方式來實現。
多路復用IO(multiplexing IO) IO multiplexing就是我們說的select,poll,epoll,有些地方也稱這種IO方式為event driven IO。 select/epoll的好處就在於單一process就可以同時處理多個網路連線的IO。
它的基本原理就是select,poll,epoll這個function會不斷的輪詢所負責的所有socket,當某個socket有資料到達了,就通知用戶進程。在IO multiplexing Model中,實際中,對於每一個socket,一般都設定為non-blocking。
但是,整個使用者的process其實是一直被block的。只不過process是被select這個函數block,而不是被socket IO給block。所以IO多工是阻塞在select,epoll這樣的系統呼叫之上,而沒有阻塞在真正的I/O系統呼叫如recvfrom之上。
訊號驅動IO(signal-driven IO)
非同步IO(asynchronous IO)使用者進程發起read作業之後,立刻就可以開始去做其它的事。而另一方面,從kernel的角度,當它受到一個asynchronous read之後,首先它會立刻返回,所以不會對用戶進程產生任何block。
然後,kernel會等待資料準備完成,然後將資料拷貝到用戶內存,當這一切都完成之後,kernel會給用戶進程發送一個signal,告訴它read操作完成了。
3、Epoll : epoll現在就很好理解了,epoll就是Linux核心為處理大批量檔案描述符而作了改進的poll,是Linux下多路復用IO介面select/poll的增強版本,它能顯著提高程式在大量並發連線中只有少量活躍的情況下的系統CPU利用率。
PS.幾個需要注意的點:
1:IO多工是同步阻塞模型還是非同步阻塞模型?
同步是需要主動等待訊息通知,而非同步則是被動接收訊息通知,透過回呼、通知、狀態等方式來被動取得訊息。 IO多路復用在阻塞到select階段時,使用者進程是主動等待並呼叫select函數取得資料就緒狀態訊息,且其進程狀態為阻塞。所以,把IO多工歸為同步阻塞模式。
2:到底什麼是並發,高並發到底是一張怎麼樣的狀態?
高並發的程式一般使用同步非阻塞方式而非多執行緒 同步阻塞方式。要理解這一點,首先要看一下並發和並行的區別。也就是說並發數是指同時進行的任務數(如同時服務的 HTTP 請求),而平行數是可以同時工作的實體資源數量(如 CPU 核數)。
透過合理調度任務的不同階段,並發數可以遠大於並行度,這就是區區幾個 CPU 可以支援上萬個使用者並發請求的奧秘。在這種高並發的情況下,為每個任務(使用者請求)建立一個進程或執行緒的開銷非常大。而同步非阻塞方式可以把多個 IO 請求丟到後台去,這就可以在一個進程裡服務大量的並發 IO 請求。
以上是Workerman中你必須知道的幾個概念的詳細內容。更多資訊請關注PHP中文網其他相關文章!