阻塞模型與非阻塞模型

2021-10-01 05:08:22 字數 2211 閱讀 8587

1.php-fpm是阻塞模型,假設你用 php-fpm,你的 php 程式中需要向外部提供介面請求。那麼每乙個 worker 程序在執行這些網路 i/o 的時候,是不是都阻塞了?假設你的 php-fpm 最大程序數有 500 個,那麼同時進來了 500 個請求,是不是都阻塞在了網路 i/o 上了?那麼接下來,php-fpm 已經無法處理第 501 個請求了。可是此時,由於在等待網路 i/o 響應,cpu 實際上並沒有做什麼工作,你會發現,cpu 很閒,但是卻無法處理請求了。

swoole是非阻塞模型,例如swoole,我們在網路 i/o 的時候,讓它去等待響應,與此同時,處理下乙個請求。那麼,我們會發現,併發數上去了,cpu 的利用率變高了。

如果只有乙個套接字的情況下,使用阻塞io是極好的,讀到資料就返回。

但是如果在有很多套接字的情況下,比如有100個套接字:

如果使用阻塞io,可能因為讀取乙個沒有資料的套接字而阻塞剩下的99個套接字的資料處理,那麼就會造成伺服器的響應性很差。

如果使用非阻塞io,那麼就需要輪詢這一百個套接字到底可不可以讀取到資料,這個輪詢操作會浪費cpu時間片,照樣也不是乙個高效的方式,套接字多了,照樣效能很差。

那有沒有一種比較好的方式來同時檢測多個套接字是否可讀可寫,並且不浪費cpu時間片呢?那就是要用io多路復用了,使用io多路復用可以同時檢測多個不同的套接字是否就緒。有多種io多路復用的實現,其中包括select,poll, epoll, /dev/poll, kqueue等。

2.nginx 是非阻塞io復用模型,通過作業系統提供的類似 epoll 的功能,可以在乙個執行緒裡處理多個客戶端的請求。

nginx 的程序就是執行緒,即每個程序裡只有乙個執行緒,但這乙個執行緒可以服務多個客戶端。

php-fpm 是阻塞的單執行緒模型,配置檔案中pm.max_children 指定的是最大的程序數量,pm.max_requests 指定的是每個程序處理多少個請求後重啟(因為 php 偶爾會有記憶體洩漏,所以需要重啟)。

php-fpm 的每個程序也只有乙個執行緒,但是乙個程序同時只能服務乙個客戶端。

大多數的 linux 程式都傾向於使用程序而不是執行緒,因為 linux 下相對來說建立程序的開銷比較小,而 linux 的執行緒功能又不是很強大。

3.首先登入nginx.com機器檢視nginx worker程序數,然後我們登入web.com機器檢視php-fpm的worker程序數(子程序數)。

非同步非阻塞

所以同步、非同步指的是傳送方,阻塞、非阻塞指的是接收方

即: 客戶端(非同步/同步) => 伺服器(阻塞/非阻塞)

這裡有個問題,非同步,客戶端請求完了,你沒給錢就讓他走了,人走了,還回得來麼?

即:服務端send(非同步/同步) => 伺服器recv(阻塞/非阻塞)

(1)為什麼用php-fpm?

cgi執行方式慢!為啥?如果nginx每次接收到乙個請求後,通過popen,執行 php index.php是什麼感覺?

apache_mod執行方式,有點慢!不靈活!apache在啟動的時候把php解析器給載入進去了,合體了!每次請求過來的時候需要通過解析器執行使用者**

fastcgi執行方式(php-fpm), 很快!通過socket和nginx通訊,解耦了!opcache快取了位元組碼不用每次解析使用者**了!

即:php-fpm是多程序的,主程序負責worker程序的排程,socket bind && listen。worker程序負責socket accept,不要懷疑為什麼worker程序同時accept不會發生驚群,linux核心已經加鎖了。worker程序就是非同步非阻塞的模型了,使用的poll函式。worker程序同一時間只執行乙個請求,所以不會因為描述符數量上公升影響poll的效率。

(2)nginx

即:nginx也是多程序的,主程序負責worker程序的排程,不處理請求。但是worker程序使用的是epoll,因為worker程序並不是同時只能處理乙個請求,他處理請求的個數是沒有限制的,直至達到伺服器的效能瓶頸。

所以我們通常把nginx的worker程序數設定為cpu核數,每個程序通過非同步非阻塞同時輪訓處理多個請求,這樣所有的worker程序可以保證cpu可以完全利用起來。

php-fpm的機器和nginx機器是一樣的,但是每個程序只能同時處理乙個請求,如果只有20個程序,cpu將長時間處於空閒狀態,非同步非阻塞會讓出cpu的使用權,這時候cpu就可以處理更多程序的任務,直至完全利用。

io模型 非阻塞模型

linux下,可以通過設定socket使其變為non blocking。當對乙個non blocking socket執行讀操作時,流程是這個樣子 從圖中可以看出,當使用者程序發出read操作時,如果kernel中的資料還沒有準備好,那麼它並不會block使用者程序,而是立刻返回乙個error。從使...

非阻塞IO模型

include include include include include include in.h include include include include include using namespace std define maxsize 2048std queue socketqu...

PythonStudy 非阻塞IO模型

服務端 import socket import time import select server socket.socket server.bind 127.0.0.1 1688 server.listen 5 server.setblocking false 預設為阻塞 設定為false 表示...