阻塞模型與非阻塞模型

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個套接字:

  1. 如果使用阻塞IO,可能因爲讀取一個沒有數據的套接字而阻塞剩下的99個套接字的數據處理,那麼就會造成服務器的響應性很差。
  2. 如果使用非阻塞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就可以處理更多進程的任務,直至完全利用。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章