日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > php >内容正文

php

PHP 技能精进之 PHP-FPM 多进程模型

發布時間:2024/7/5 php 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 PHP 技能精进之 PHP-FPM 多进程模型 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

PHP-FPM 提供了更好的 PHP 進程管理方式,可以有效控制內存和進程、可以平滑重載PHP配置。那么當我們談論 PHP-FPM 多進程模型的時候,作為 PHPer 的你了解多少呢?

首先,讓我們一起看幾個問題:

①:PHP-FPM 啟動進程的方式主要有哪幾種,區別是什么?

②:PHP-FPM,是主進程接收請求轉給子進程,還是子進程單獨接收請求并處理,如何驗證?

③:為何在 PHP-FPM 模式下,PHP 代碼很少有人去做連接池?

④:PHP-FPM 模式性能差的體現有哪些,如何優化?

⑤:PHP-FPM 模式下的 YAC 為何無法和 CLI 模式無法共享內存?

1. 如何啟動進程

PHP-FPM 是多進程模式,由 Master 進程管理 Worker 進程。進程的數量,都可以通過 php-fpm.conf 做具體配置。?PHP-FPM 的進程可以分為動態模式及靜態模式:

①:靜態(Static)

直接開啟指定數量的 PHP-FPM 進程,不再增加或者減少;啟動固定數量的進程,占用內存高。但在用戶請求波動大的時候,對 Linux 操作系統進程的處理上耗費的系統資源低。

②:動態(Dynamic)

開始時開啟一定數量的 PHP-FPM 進程,當請求量變大的時候,動態增加 PHP-FPM?進程數到上限,當空閑的時候自動釋放空閑進程數到一個下限。

動態模式會根據 max、min、idle children 配置,動態的調整進程數量。在用戶請求較為波動,或者瞬間請求增高的時候,動態模式下會進行大量進程的創建、銷毀等操作,而造成 Linux 負載波動升高。簡單來說,請求量少,PHP-FPM 進程數少,請求量大,進程數多。優勢就是,當請求量小的時候,進程數少,內存占用也小。

③:按需 (Ondemand)

這種模式下,PHP-FPM 的 Master 不會 Fork 任何子進程,純粹就是按需啟動。

這種模式通常很少使用,因為它基本無法適應有一定量級的線上業務。由于 php-fpm 是短連接的,所以每次請求都會先建立連接,建立連接的過程必然會觸發上圖的執行步驟。所以,在大流量的系統上 Master 進程會變得繁忙,占用系統 CPU 資源,不適合大流量環境的部署。

借用一張網絡圖片來說明:

需要注意 2 個點,「連接」和「數據」到來。有連接進來再 Fork 進程,同樣可以達到子進程繼承父進程上下文,然后子進程處理用戶請求這個目的。

(關于動態、靜態進程模式的相關參數,可參考 PHP 官方文檔。)

我們需要關注的是對于我們自身的業務,應該選擇的 PHP-FPM 模式為動態還是靜態。

通常來說,對于比較大內存的服務器,設置為靜態的話會提高效率。因為頻繁開關 php-fpm 進程也會有時滯,所以內存夠大的情況下開靜態效果會更好。數量也可以根據 內存/30M 得到。比如說 2GB 內存的服務器,可以設置為 50;4GB 內存可以設置為 100 等。高配機器選靜態,低配機器(省內存)選動態,高配機器用動態不能充分利用內存資源和 CPU 資源,也無法及時應對瞬時高并發。

2.?如何進行請求處理和驗證

PHP-FPM 的進程管理方式和 Nginx 的進程管理方式有些類似。在處理請求時,并非由主進程接受請求后轉給子進程,而是子進程「搶占式」地接受用戶請求。本質上 PHP-FPM 多進程以及 Nginx 多進程,都是在主進程監聽同一個端口后,Fork 子進程達到多個進程監聽同一端口的目的。

Linux 系統所有的進程 IO 操作,都需要和操作系統打交道。也就是說,系統知道所有 IO 操作。這個過程就是我們常說的「系統調用」。我們可以從系統調用入手解決這個問題。系統調用的查看,可以使用 Strace。

如何驗證相對簡單,我們可以采取 2 種方式:

  • 看 PHP-FPM 進程的日志。這需要配置好合適的 PHP-FPM 日志格式;
  • 既然 IO 數據會通過內核態過度到用戶態進程,我們可以通過 strace -p <pid> 命令去跟蹤系統調用。分別跟蹤 PHP-FPM 的主進程 ID 以及子進程 ID,然后訪問 Nginx,由 Nginx 通過 fast-cgi 協議轉到 PHP-FPM 進程上,看在哪個進程上發送了系統調用。

3. 為何不在 PHP-FPM 下做代碼連接池 ?

首先,在 PHP-FPM 模式下,一個請求的生命周期注定只有 1 次。也就是說,從 FPM 請求到請求、解析 PHP 腳本,到 FPM 的 Zend 虛擬機分配資源執行,再到最后的處理結束,PHP-FPM 會回收這次請求的所有資源。

這種方式一是為了讓開發不需要關心資源的回收處理,所以你可能沒怎么關心過網絡的關閉、文件描述符的關閉等等。二是為了減少內存溢出的情況。

如果在這種模式下,你實現了連接池,也意味著請求結束,連接池消失,做了一次無用功而已。

「雞肋的」PConnect(持久化鏈接)。持久化鏈接也就是鏈接不釋放。但問題在于,PHP-FPM 是多進程模式,而持久化的鏈接存在于進程中。這就意味著,如果一臺機器有 300 個 FPM 進程,會一次性初始化 300 個持久化鏈接。如果因為面臨業務活動需求冒然對機器擴容,很可能造成業務的數據庫連接數直接打滿。

4. 如何優化性能

首先,我們應該思考導致性能差可能的原因是什么。如果一個應用的性能差,我們往往會從 2 個方面來分析,一個是 IO 性能,一個是計算性能。

IO 方面,因為 PHP-FPM 模式下難以做連接池,所以高并發業務下的網絡處理會有劣勢。注意我這里一直說的都是 PHP-FPM 模式下,在 CLI 模式下還是可以自己做連接池的。只不過這個連接池僅限于 CLI 模式的單進程內,而且這個模式不能用于處理網絡請求(比如 HTTP 請求)。因為 PHP 默認單進程模式,FPM、CLI 都是默認單進程,即便 CLI 可以做連接池 ,也不方便做鏈接保活(不能同時做心跳檢測)。

計算性能上來說,雖然 PHP 是用 C 寫的,如果單純論計算性能是不錯的。但問題在于 PHP 處理請求時,每次都要解析 PHP 腳本、翻譯 PHP 代碼為 Opcode、用 Zend 虛擬機執行 Opcode,處理結束,釋放資源。經歷這樣的過程?是導致 PHP 計算性能慢的最大原因之一。

如何優化:

  • 對于計算性能來說,使用 Zend OPcache 擴展,緩存字節碼。
  • 對于**?IO 性能**來說,使用文件 cache 或者 memcached 減輕對網絡 Cache 的壓力;使用 Yac 減輕對 Cache 層的壓力;在同一次請求中;復用鏈接不要每次都用新的;合理設計日志組件類庫,優化 Logger 減少對文件操作的次數來減少 IO 的壓力。

關于設計一個合格的 Logger 組件,我們需要注意幾個點:

① 每次請求,只做一次日志寫操作,不要每次別人調用你的函數,你都去執行一次類似 file_put_contents 的操作。

② 兼容各種類似錯誤。換句話說,即使 PHP fatal error 了,你也得能把知名錯誤之前的日志記錄下來。這個實現可以借助 PHP 類的析構方法來做。也可以使用更好的 register_shutdown_function 來注冊一個鉤子,在 PHP 請求結束的時候,回調此鉤子,完成做最后的日志操作。

5. YAC 為何無法和 CLI 模式共享內存

我們知道,PHP 擴展開發中首要執行的一個宏是?PHP_MINIT_FUNCTION。YAC 擴展需要在 PHP-FPM 進程啟動時起就初始化一塊共享內存,供各個進程來共享使用。因此,實現共享的關鍵在于需要一個讓各個進程都知道的相同標識。

YAC 擴展的初始化流程為:

我們查看 create_segments 的具體實現:

上面做了一些注釋,最關鍵的是要開啟共享內存需要的系統 ID,shared_segment_name,此值包含了進程?ID。也就是 PHP-FPM 的主進程 ID。有相同的共享內存標識 ID,就是 PHP-FPM 模式所有進程間能夠通信的奧秘所在。而如果我們是想要通過 PHP 腳本使用 yac 擴展讀取這個共享內存,會這樣做:

在 CLI 模式下,這樣是不可能拿到 PHP-FPM 模式下設置的共享內存數據的。因為 CLI 模式下執行 PHP 腳本、進程 ID,和 PHP-FPM 模式下的進程 ID 完全不相同。

后面的文章中,我們會找機會講一講進程間通訊,以及基于共享內存的通訊。總結來說,多進程要共享內存通信,必須要一開始就協調好一個唯一 ID。這個 ID 多個進程間都要知道。PHP-FPM 是多進程,主進程 fork 子進程出來,子進程自然知道這個唯一 ID 是什么(因為 Linux 進程 fork 會把整個進程的堆棧內存都 fork 一遍)。但是,php a.php 這樣執行,其實是一個完全獨立的進程,和 PHP-FPM 沒任何關系,這樣的進程,也就不能知道 PHP-FPM 進程里的那個唯一 ID 是什么。

本文作者:董紅帥,馬蜂窩系統部研發工程師。?

關注馬蜂窩技術(微信ID:mfwtech),找到更多你想要的內容。

?

轉載于:https://www.cnblogs.com/mfwtech/p/10516703.html

總結

以上是生活随笔為你收集整理的PHP 技能精进之 PHP-FPM 多进程模型的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。