溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Workerman中reusePort屬性的作用是什么

發(fā)布時(shí)間:2021-07-24 11:40:54 來源:億速云 閱讀:158 作者:Leah 欄目:編程語言

這篇文章將為大家詳細(xì)講解有關(guān)Workerman中reusePort屬性的作用是什么,文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個(gè)參考,希望大家閱讀完這篇文章后對相關(guān)知識(shí)有一定的了解。

Workerman是一個(gè)高性能的PHP Socket服務(wù)器框架。可以用 Workerman 直接在 TCP 層編程,基本的編程套路是:

$w = new Workerman\Worker('tcp://0.0.0.0:80');
$w->count = 4;
$w->onMessage = function(Workerman\COnnection\TcpConnection $connection, array $data) {
    $connection->send('Hello World');
};
Worker::runAll();

在使用的過程中,不知道你是否留意過 reusePort 這個(gè)參數(shù),他默認(rèn)被設(shè)置為 false。這個(gè)參數(shù)有什么用?什么情況下我們需要把他設(shè)置為 true,從而提高性能呢?

1. reuseport 的作用

關(guān)于 reusePort 參數(shù),Workerman官方的文檔是這么解釋的:

開啟監(jiān)聽端口復(fù)用后允許多個(gè)無親緣關(guān)系的進(jìn)程監(jiān)聽相同的端口,并且由系統(tǒng)內(nèi)核做負(fù)載均衡,決定將socket連接交給哪個(gè)進(jìn)程處理,避免了驚群效應(yīng),可以提升多進(jìn)程短連接應(yīng)用的性能。

如果沒有深入研究過 Linux 網(wǎng)絡(luò)編程,很難理解這句話。在此簡單解釋一下:

服務(wù)端程序通常通過監(jiān)聽服務(wù)器上的某個(gè)端口號(hào),來接收客戶端的請求。在Linux中,服務(wù)器網(wǎng)卡 + 端口號(hào)被抽象成了一個(gè) Socket

為了提升性能,一般的服務(wù)端程序在運(yùn)行時(shí)都有多個(gè)進(jìn)程(俗稱 Worker)監(jiān)聽同一個(gè) Socket,在沒有客戶端連接到來的時(shí)候,這些Worker是處于掛起狀態(tài)的,不消耗CPU資源。

如果某一刻有一個(gè)客戶端連接到來,Linux 內(nèi)核就會(huì)同時(shí)喚醒這些 Worker,讓他們競爭去處理這個(gè)連接,

結(jié)果只有一個(gè) Worker 可以獲得處理這個(gè)連接的機(jī)會(huì),其他Worker在競爭失敗后繼續(xù)回到掛起狀態(tài)。喚醒 Worker 的過程是要消耗CPU資源的,Worker 數(shù)量越多,消耗的 CPU 資源就越多,造成了資源的浪費(fèi)。這就是常說的 驚群效應(yīng)。

你也許會(huì)問:為什么不每次只喚醒一個(gè)Worker呢?很遺憾,Linux內(nèi)核并沒有這樣的功能。

幸好,在 Linux 3.9 及以后的版本,加入 reuseport 特性。這個(gè)特性有什么用呢?

在有 reuseport 之前,一個(gè)端口號(hào)只能被一個(gè) Socket 監(jiān)聽,有了 reuseport 之后,這個(gè)限制就被打破了:一個(gè)端口號(hào)可以被多個(gè) Socket 同時(shí)監(jiān)聽。

前面說到,Linux 內(nèi)核沒法做到一次只喚醒一個(gè) Worker,但是,內(nèi)核可以做到將客戶端連接均勻地發(fā)送到監(jiān)聽統(tǒng)一端口的一群 Socket 上。

如圖所示,每個(gè) Worker 都有自己的 Socket,都監(jiān)聽同一個(gè)端口。當(dāng)有客戶端連接到來時(shí),內(nèi)核轉(zhuǎn)發(fā)連接到一個(gè) Socket 上,而這個(gè) Socket 只會(huì)喚醒自己隸屬的那個(gè) Worker。這樣就很巧妙地解決了 驚群效應(yīng),提高了整體的性能。

由此,我們可以得出結(jié)論:如果你的 Linux 內(nèi)核版本是 3.9 及以上的話,那么在使用 Workerman 時(shí),可以將 reusePort 設(shè)置為 true 提升程序運(yùn)行效率。

2. Workerman 如何利用 reuseport

雖然你只要在 Workerman 中把 reusePort 設(shè)置為 true,就能享受到 Linux 的這個(gè)高級特性。但 Workerman 的源碼中,并不只是開啟一個(gè)內(nèi)核參數(shù)那么簡單。Workerman 為你隱藏了許多的設(shè)計(jì)細(xì)節(jié),我們來研究下。

Worker 類是 Workerman 里最主要的類,其中有個(gè) listen() 函數(shù):

protected function listen()
{
    ...
    if (!$this->_mainSocket) {
        ...
        $this->_mainSocket = stream_socket_server(...);
        ...
    }
    ...
}

listen() 函數(shù)的作用就是在當(dāng)前進(jìn)程創(chuàng)建一個(gè) Socket 并開始監(jiān)聽請求。

當(dāng) reusePort 為 false 時(shí),主進(jìn)程在創(chuàng)建 Worker 之前就調(diào)用了 listen() 函數(shù):

protected function initWorkers() {
    ....
    if (!$worker->reusePort) {
        $worker->listen();
    }
    ....
}

隨后主進(jìn)程通過 pcntl_fork() 創(chuàng)建 Worker。pcntl_fork() 有個(gè)特性:創(chuàng)建出來的子進(jìn)程(Worker)中的變量都是父進(jìn)程復(fù)制而來的,包括父進(jìn)程創(chuàng)建的 mainSocket。所以,當(dāng)reusePort為??false??時(shí),所有的Worker都復(fù)制父進(jìn)程的mainSocket。所以,當(dāng)reusePort為??false??時(shí),所有的Worker都復(fù)制父進(jìn)程的_mainSocket,也即共用一個(gè) Socket。

而當(dāng) reusePort 為 true 時(shí),情況就不同了。主進(jìn)程在創(chuàng)建 Worker 前不會(huì)調(diào)用 listen(),而是在創(chuàng)建完 Worker 后由每個(gè) Worker 自行發(fā)起 listen() 調(diào)用:

protected static function forkOneWorkerForLinux($worker) {
    ...
    $pid = pcntl_fork();
    if ($pid === 0) {
        if ($worker->reusePort) {
            $worker->listen();
        }
        ...
    }
    ...
}

這樣的結(jié)果就是,每個(gè)子進(jìn)程(Worker)都創(chuàng)建了自己的 Socket。

最后還有一點(diǎn),如果想要內(nèi)核開啟 reuseport 功能,需要手動(dòng)設(shè)置 Socket 的 context:

if ($this->reusePort) {
    $context = stream_context_create();
    stream_context_set_option($context, 'socket', 'so_reuseport', 1);
}

關(guān)于Workerman中reusePort屬性的作用是什么就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI