91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

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

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

Workerman中reusePort屬性的作用是什么

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

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

Workerman是一個高性能的PHP Socket服務器框架。可以用 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 這個參數,他默認被設置為 false。這個參數有什么用?什么情況下我們需要把他設置為 true,從而提高性能呢?

1. reuseport 的作用

關于 reusePort 參數,Workerman官方的文檔是這么解釋的:

開啟監聽端口復用后允許多個無親緣關系的進程監聽相同的端口,并且由系統內核做負載均衡,決定將socket連接交給哪個進程處理,避免了驚群效應,可以提升多進程短連接應用的性能。

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

服務端程序通常通過監聽服務器上的某個端口號,來接收客戶端的請求。在Linux中,服務器網卡 + 端口號被抽象成了一個 Socket

為了提升性能,一般的服務端程序在運行時都有多個進程(俗稱 Worker)監聽同一個 Socket,在沒有客戶端連接到來的時候,這些Worker是處于掛起狀態的,不消耗CPU資源。

如果某一刻有一個客戶端連接到來,Linux 內核就會同時喚醒這些 Worker,讓他們競爭去處理這個連接,

結果只有一個 Worker 可以獲得處理這個連接的機會,其他Worker在競爭失敗后繼續回到掛起狀態。喚醒 Worker 的過程是要消耗CPU資源的,Worker 數量越多,消耗的 CPU 資源就越多,造成了資源的浪費。這就是常說的 驚群效應

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

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

在有 reuseport 之前,一個端口號只能被一個 Socket 監聽,有了 reuseport 之后,這個限制就被打破了:一個端口號可以被多個 Socket 同時監聽。

前面說到,Linux 內核沒法做到一次只喚醒一個 Worker,但是,內核可以做到將客戶端連接均勻地發送到監聽統一端口的一群 Socket 上。

如圖所示,每個 Worker 都有自己的 Socket,都監聽同一個端口。當有客戶端連接到來時,內核轉發連接到一個 Socket 上,而這個 Socket 只會喚醒自己隸屬的那個 Worker。這樣就很巧妙地解決了 驚群效應,提高了整體的性能。

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

2. Workerman 如何利用 reuseport

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

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

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

listen() 函數的作用就是在當前進程創建一個 Socket 并開始監聽請求。

當 reusePort 為 false 時,主進程在創建 Worker 之前就調用了 listen() 函數:

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

隨后主進程通過 pcntl_fork() 創建 Worker。pcntl_fork() 有個特性:創建出來的子進程(Worker)中的變量都是父進程復制而來的,包括父進程創建的 mainSocket。所以,當reusePort為??false??時,所有的Worker都復制父進程的mainSocket。所以,當reusePort為??false??時,所有的Worker都復制父進程的_mainSocket,也即共用一個 Socket。

而當 reusePort 為 true 時,情況就不同了。主進程在創建 Worker 前不會調用 listen(),而是在創建完 Worker 后由每個 Worker 自行發起 listen() 調用:

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

這樣的結果就是,每個子進程(Worker)都創建了自己的 Socket。

最后還有一點,如果想要內核開啟 reuseport 功能,需要手動設置 Socket 的 context:

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

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

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

长武县| 蓬溪县| 拉孜县| 即墨市| 安新县| 碌曲县| 新郑市| 盘锦市| 丽水市| 鄄城县| 姜堰市| 清徐县| 孝义市| 普洱| 万州区| 吴江市| 牟定县| 望江县| 嘉义县| 梅河口市| 苗栗市| 灯塔市| 涟源市| 青海省| 吴忠市| 乌拉特中旗| 炉霍县| 从江县| 富宁县| 普安县| 栖霞市| 德清县| 平和县| 阿尔山市| 亳州市| 安平县| 包头市| 黄龙县| 永川市| 巴林左旗| 黔南|