中文字幕理论片,69视频免费在线观看,亚洲成人app,国产1级毛片,刘涛最大尺度戏视频,欧美亚洲美女视频,2021韩国美女仙女屋vip视频

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
【Swoole系列3.2】Swoole 異步進程服務(wù)系統(tǒng)

Swoole 異步進程服務(wù)系統(tǒng)

在了解了整個進程、線程、協(xié)程相關(guān)的知識后,我們再來看看在 Swoole 中是如何通過異步方式處理進程問題的,并且了解一下線程在 Swoole 中的作用。

Server兩種運行模式

其實在之前的測試代碼中,我們就已經(jīng)見到過這兩種模式了,只是當時沒說而已。不管是 Http 還是 TCP 等服務(wù)中,我們都有第三個參數(shù)的存在,默認情況下,它會賦值為一個 SWOOLE_PROCESS 參數(shù),因此,如果是默認情況下我們一般不會寫這個參數(shù)。而另外一種模式就是 SWOOLE_BASE 。

SWOOLE_BASE模式

這種模式就是傳統(tǒng)的異步非阻塞模式,它的效果和 Nginx 以及 Node.js 是完全一樣的。在 Node.js 中,是通過一個主線線程來處理所有的請求,然后對 I/O 操作進行異步線程處理,避免創(chuàng)建、銷毀線程以及線程切換的消耗。當 I/O 任務(wù)完成后,通過觀察者執(zhí)行指定的回調(diào)函數(shù),并把這個完成的事件放到事件隊列的尾部,等待事件循環(huán)。

這個東西吧,要講清楚,開一個大系列都不為過。但是如果你之前學習過一點 Node 的話,那么其實就很好理解。因為我們之前寫的各種 Server 服務(wù)代碼,其實和 Node 中寫得基本完全一樣。都是一個事件,然后監(jiān)聽成功后在回調(diào)函數(shù)中寫業(yè)務(wù)代碼。這就是通過回調(diào)機制來實現(xiàn)的異步非阻塞模式,將耗時操作放在回調(diào)函數(shù)中。有興趣的同學可以去簡單地學習一下 Node.js ,只要有 JS 基礎(chǔ),一兩看看完一套入門教程就可以了。

在 Swoole 的 SWOOLE_BASE 模式下,原理也是完全一樣的。當一個請求進來的時候,所有的 Worker 都會爭搶這一個連接,并最終會有一個 Worker 進程成功直接和客戶端建立連接,之后這個連接中所有的數(shù)據(jù)收發(fā)直接和這個 Worker 通訊,不再經(jīng)過主進程的 Reactor 線程轉(zhuǎn)發(fā)。

SWOOLE_PROCESS模式

SWOOLE_PROCESS 的所有客戶端都是和主進程建立的,內(nèi)部實現(xiàn)比較復雜,用了大量的進程間通信、進程管理機制。適合業(yè)務(wù)邏輯非常復雜的場景,因為它可以方便地進行進程間的互相通信。

在 SWOOLE_PROCESS 中,所有的 Worker 不會去爭搶連接,也不會讓某一個連接與某個固定的 Worker 通訊,而是通過一個主進程進行連接。剩下的事件處理則交給不同的 Worker 去執(zhí)行,當?shù)竭_ Worker 之后,同樣地也是使用回調(diào)方式進行處理了,后續(xù)內(nèi)容基本就和 BASE 差不多了。也就是說,Worker 功能的不同是它和 SWOOLE_BASE 最大的差異,它實現(xiàn)了連接與數(shù)據(jù)請求的分離,不會因為某些連接數(shù)據(jù)量大某些量小導致 Worker 進程不均衡。具體的方式就是在這種模式下,會多出來一個主管線程的進程,其中還會有一個非常重要的 Reactor 線程,下面我們再詳細說明。

兩種模式的異同與優(yōu)缺點

如果客戶端之間不需要交互,也就是我們普通的 HTTP 服務(wù)的話,SWOOLE_BASE 模式是一個很好的選擇,但是它除了 send() 和 close() 方法之外,不支持跨進程執(zhí)行。但其實,這兩種模式在底層的處理上沒什么太大的區(qū)別,都是走的異步IO機制。只是說它們的連接方式不同。SWOOLE_BASE 的每個 Worker 都可以看成是 SWOOLE_PROCESS 的 Reactor 線程和 Worker 進程兩部分的組合。

我們可以來測試一下。

$http = new Swoole\Http\Server('0.0.0.0'9501, SWOOLE_BASE);

//$http = new Swoole\Http\Server('0.0.0.0', 9501, SWOOLE_PROCESS);

$http->set([
    'worker_num'=>2
]);

$http->on('Request'function ($request, $response) {
    var_dump(func_get_args());
    $response->end('開始測試');
});

$http->start();

通過切換上面兩個注釋,我們就可以查看兩種服務(wù)運行模式的情況,可以通過 pstree -p 命令。

在 SWOOLE_BASE 模式下,輸出的內(nèi)容是這樣的。

可以看到,在 1629 這個進程下面有兩個子進程 1630 和 1631 。然后切換成 SWOOLE_PROCESS 模式,再查看進程情況。


很明顯,這里不一樣了,在 1577 這個 Master 主進程下,有兩個進程,一個是 1578 ,一個是 1579 它表示的是線程組,然后在 1578 Manager 管理進程下面,又有 1580 和 1581 兩個 Worker 進程。

同樣地,我們使用之前在 【Swoole教程2.5】異步任務(wù)https://mp.weixin.qq.com/s/bQt9Ul-H34eUYw2-Qu-N0g 中的代碼來測試,可以看到 Task 異步任務(wù)也是起的進程。(注意,我們在測試代碼中設(shè)置的是 task_worker_num,沒有設(shè)置 worker_num ,所以是 1個Worker + 4個 TaskWorker 進程,最后再加一個 PROCESS 模式的 線程組 )如果如圖所示。


到這里,相信你也看出了,SWOOLE_BASE 比 SWOOLE_PROCESS 少了一層進程的遞進,也就是少了一個層級。在 SWOOLE_BASE 模式下,沒有 Master 進程,只有一個 Manager 進程,另外就是沒有從 Master 中分出來的線程組。關(guān)于 Master/Manager/Reactor/TaskWorker 這些東西我們下一小節(jié)就會說到。

BASE 模式因為更簡單,所以不容易出錯,它也沒有 IPC 開銷,而 PROCESS 模式有 2 次 IPC 開銷,master 進程與 worker 進程需要 Unix Socket 進行通信。IPC 這東西就是同一臺主機上兩個進程間通信的簡稱。它一般有兩種形式,一個是通過 Unix Socket 的方式,就是我們最常見的類似于 php-fcgi.sock 或者 mysql.sock 那種東西。另一種就是 sysvmsg 形式,這是 Linux 提供的一種消息隊列,一般使用的比較少。

當然,BASE 模式也有它自身存在的問題,主要也是因為上面講過的特性。由于 Worker 是和連接綁定的,因此,某個 Worker 掛掉的話,這個 Worker 里面的所有連接都會被關(guān)閉。另外由于爭搶的情況,Worker 進程無法實現(xiàn)均衡,有可能有些連接數(shù)據(jù)量小,負載也會非常低。最后,如果回調(diào)函數(shù)中阻塞操作,會導致 Server 退化為同步模式,容易導致 TCP 的 backlog 隊列塞滿。不過就像上面說過的,Http 這種無狀態(tài)的不需要交互的連接,使用 BASE 沒什么問題,而且效率也是非常 OK 的。當然,既然默認情況下 Swoole 已經(jīng)為我們提供的是 SWOOLE_PROCESS 進程了,那么也就說明 SWOOLE_PROCESS 模式是更加推薦的一種模式。

各種進程問題

接下來,我們繼續(xù)學習上面經(jīng)常會提到的各種進程和線程問題。

Master 進程

它是一個多線程進程。用于管理線程,它會創(chuàng)建 Master 線程以及 Reactor 線程,并且還有心跳檢測線程、UDP 收包線程等等。

Reactor 線程

這個線程我們不止一次提到了,它是在 Master 進程中創(chuàng)建的,負責客戶端 TCP 連接、處理網(wǎng)絡(luò) IO 、處理協(xié)議、收發(fā)數(shù)據(jù),它不執(zhí)行任何 PHP 代碼,用于將 TCP 客戶端發(fā)來的數(shù)據(jù)緩沖、拼接、拆分成完整的一個請求數(shù)據(jù)包。我們在 Swoole 代碼中操作不了線程,為什么呢?其實 PHP 本身就是不支持多線程的,Swoole 是一種多進程應(yīng)用框架。在這里的線程是在底層用 C/C++ 封裝好的。因此,也并沒有為我們提供可以直接操作線程的接口。但我們已經(jīng)學習過了,協(xié)程本身就是工作在線程之上的,而且,協(xié)程也已經(jīng)是現(xiàn)在的主流方向了,所以在 Swoole 中,進程管理和協(xié)程,才是我們學習的重點。

Worker 進程

Worker 是接受 Reactor 線程投遞過來的請求數(shù)據(jù)包,并執(zhí)行具體的 PHP 回調(diào)函數(shù)來進行數(shù)據(jù)處理的。在處理完成之后,將生成的響應(yīng)數(shù)據(jù)發(fā)送回 Reactor 線程,再由 Reactor 發(fā)送給客戶端。Worker 進程可以是異步非阻塞模式的,也可以是同步阻塞模式的,并且是以多進程方式運行的。

TaskWorker 進程

它是接受收 Worker 進程投遞過來的任務(wù),處理任務(wù)后將結(jié)果返回給 Worker 進程,這種模式是同步阻塞的模式,同樣它也是以多進程的方式運行的。

Manager 進程

這個進程主要負責創(chuàng)建、回收 Worker/TaskWorkder 進程。其實就是一個進程管理器。

它們的關(guān)系

首先,我們先來看兩張圖,也是官網(wǎng)給出的圖,并根據(jù)這兩張圖再來看看官網(wǎng)給出的例子。


第一張圖主要是 Manager 和 Master 的功能。我們主要看第二張圖。


在這張圖中,我們可以看到,Manager 進程創(chuàng)建、回收、管理最下面的 Worker 進程和 Task 進程。并且是通過操作系統(tǒng)的 fork() 函數(shù)創(chuàng)建的,這個東西如果學過操作系統(tǒng)的同學應(yīng)該不會陌生,fork() 就是創(chuàng)建子進程的函數(shù)。子進程間通過 Unix Socket 或者 MQ 隊列進行通信。如果你是 BASE 模式,那么就不會有 Master 進程,這個時候,每一個 Worker 進程自己會承擔起 Reactor 的功能,接收、響應(yīng)請求數(shù)據(jù)。

如果你是使用的 PROCESS 模式,那么上面的 Master 進程就會創(chuàng)建各種線程,還記得那個大括號的線程組吧,這個可是 BASE 模式?jīng)]有的。它用于處理請求響應(yīng)問題,不用想,多線程方式對于連接請求來說效率會更高。這也是前面說過的兩種模式的優(yōu)缺點的具體體現(xiàn)。然后 Reactor 線程通過 Unix Socket 與 Worker 進行通訊,完成數(shù)據(jù)向 Worker 的轉(zhuǎn)發(fā)與接收。

我們用官網(wǎng)給出的例子來再說明一下它們之間的關(guān)系。Reactor 就是 nginx,Worker 就是 PHP-FPM 。Reactor 線程異步并行地處理網(wǎng)絡(luò)請求,然后再轉(zhuǎn)發(fā)給 Worker 進程中去處理。Reactor 和 Worker 間通過 Unix Socket 進行通信。

在 PHP-FPM 的應(yīng)用中,經(jīng)常會將一個任務(wù)異步投遞到 Redis 等隊列中,并在后臺啟動一些 PHP 進程異步地處理這些任務(wù)。這個場景相信大家都不會陌生吧,比如說我們下了訂單之后,在原生 PHP 環(huán)境下進行消息通知、郵件發(fā)送,我們都會直接將這種問題放到一個隊列中,然后讓后臺跑起一個腳本去消費這些隊列從而進行信息發(fā)送。而 Swoole 提供的 TaskWorker 則是一套更完整的方案,將任務(wù)的投遞、隊列、PHP 任務(wù)處理進程管理合為一體。通過底層提供的 API 可以非常簡單地實現(xiàn)異步任務(wù)的處理。另外 TaskWorker 還可以在任務(wù)執(zhí)行完成后,再返回一個結(jié)果反饋到 Worker。

一個更通俗的比喻,假設(shè) Server 就是一個工廠,那 Reactor 就是銷售,接受客戶訂單。而 Worker 就是工人,當銷售接到訂單后,Worker 去工作生產(chǎn)出客戶要的東西。而 TaskWorker 可以理解為行政人員,可以幫助 Worker 干些雜事,讓 Worker 專心工作。

上述內(nèi)容需要好好理解,特別是對于我們些長年接觸傳統(tǒng)的 PHP-FPM 模式開發(fā)的同學來說,要轉(zhuǎn)換思維很不容易。不過根據(jù)官方提供的例子,相信大家也能很快把這個彎轉(zhuǎn)過來。普通的請求就是把我們的 Nginx+PHP-FPM 給結(jié)合起來了,而 Task 則是可以處理一些類似于消息隊列的異步操作。

Swoole 服務(wù)運行流程

最后,我們再來了解一下整體 Swoole 服務(wù)的運行流程,同樣也是來自官網(wǎng)的圖片。


其實這個流程圖和我們的代碼流程非常類似。定義一個 Server 對象,使用 set() 方法設(shè)置參數(shù),然后使用 on() 方法開始監(jiān)聽各種回調(diào),最后 start() 方法啟動服務(wù)。在服務(wù)啟動之后,創(chuàng)建了 Manager 進程,如果是 PROCESS 模式的話,則是先創(chuàng)建一個 Master 進程,然后在 Master 之下創(chuàng)建 Manager 。接著,Manager 根據(jù) tasker_num 數(shù)量創(chuàng)建并管理相對應(yīng)數(shù)量的 Worker 進程。其中,可以在 Worker 中創(chuàng)建異步的 task 進程。

Reactor 線程在最外面處理請求響應(yīng)問題,監(jiān)聽相對應(yīng)的事件,并與 Worker 進行通信。如果是 BASE 模式,不存在 Reactor 線程,則是全部由 Worker 來解決,而且它與連接的關(guān)系是一對一的。

總結(jié)

又是讓人暈頭轉(zhuǎn)向的一篇文章吧。在今天的學習中,最主要的其實還是一種思維的轉(zhuǎn)變,那就是我們要通過多進程的方式來提供服務(wù)應(yīng)用。而且這種模式其實并不陌生,Nginx+PHP-FPM 就是這種模式,只不過,PHP-FPM 本身就是一個進程管理工具,但它的效率以及實現(xiàn)方式都與 Swoole 略有差別。包括在 PHP8 之后的 JIT ,它就是通過 OPCahce 來實現(xiàn)的,也是在將大部分代碼全部一次加載到內(nèi)存中,就像 Swoole 一樣節(jié)約每次 PHP-FPM 的全量加載問題從而提升性能。

好好消化吸收一下吧,不過同樣的,如果上述內(nèi)容有錯誤紕漏,隨時歡迎大家指正批評,畢竟水平有限。

測試代碼:

https://github.com/zhangyue0503/swoole/blob/main/3.Swoole%E8%BF%9B%E7%A8%8B/source/3.2Swoole%E5%BC%82%E6%AD%A5%E8%BF%9B%E7%A8%8B%E7%B3%BB%E7%BB%9F.php

參考文檔:

https://wiki.swoole.com/#/server/init

https://wiki.swoole.com/#/learn?id=process-diff

本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊舉報
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
Swoole的進程模型
PHP并發(fā)IO編程之路[轉(zhuǎn)]
Apache與Nginx的區(qū)分比較 | nginx vs apache | nginx apache 比較 | apache和nginx
要學swoole看這個 比看文檔強多了 (文末有福利)
PHP開發(fā)者的福音,解讀PHP異步通信框架Swoole的機制
Swoole
更多類似文章 >>
生活服務(wù)
熱點新聞
分享 收藏 導長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服