首頁  >  文章  >  後端開發  >  一文帶你深入剖析PHP-FMP

一文帶你深入剖析PHP-FMP

青灯夜游
青灯夜游轉載
2021-06-08 18:40:492763瀏覽

本篇文章要為大家詳解介紹一下PHP-FMP。有一定的參考價值,有需要的朋友可以參考一下,希望對大家有幫助。

一文帶你深入剖析PHP-FMP

什麼是php-fpm

  • 在了解php-fpm之前,請大家先思考一個問題,一個使用者發起了一個web(niginx伺服器)請求,在php程式碼裡面,那麼我們怎麼樣才可以透過$_POST,$_GET,$_SERVER來取得一些請求資訊呢?我們該參考什麼格式去組裝資料呢?

其實我們知道,每種動態語言,也就是解釋性語言,都需要透過對應的解析器才能被伺服器(這裡指web伺服器)識別,但是解釋器和伺服器必須遵循某種協議,雙方才能夠正常通信,那麼這種協議就是CGI協議,但是CGI的機制是每響應一次web請求,都會創建和初始化一個新的處理進程,請求結束就kill掉這個進程。那每次請求,都要執行這三步驟  創建->初始化->結束,那其實這個過程不僅浪費了資源,而且效率也很低。那怎麼辦? FastCGI應時而生,作為CGI的改良版本,FastCGI會啟動一個常駐服務進程,這個進程不需要管理生命週期,也就避免了進程的重複的創建和結束,另一方面,不需要再重複的讀取環境變數,每當有web請求過來,由FastCGI管理器,也就那個常駐服務進程去啟動CGI解釋器進程

一文帶你深入剖析PHP-FMP

  • 好了,既然有了CGI,那麼針對這些解釋性語言,例如php phython,都要依照自己的語言做一個適配吧。那麼php官方就弄出來了PHP-CGI,php定製版的CGI。
  • 但隨著使用,大家發現了PHP-CGI的問題

1.修改php.ini 後必須重啟PHP-CGI才可以生效,而無法實現平滑重啟 2.直接幹掉PHP-CGI,php就不能運作了,這顯然是不能接受的 3.這玩意不會自己管理進程,它只能解析請求,回傳結果

那麼FastCGI都已經到來了,php的FastCGI還會遠嗎,當然不會,到2004年一個叫Andrei Nigmatulin的屌絲發明了PHP-FPM,PHP-FMP 全名叫做PHP-FASTCGI Process Manager,說白了就是php定製版的FastCGI(這裡強調一下,不管是PHP-CGI 還是PHP-FPM都是為了實現CGI協議,而不是新的協議),其實有一句話剛才我沒說,網路上很多人說PHP-CGI 就是php管理FAST-CGI的一種程序,那你現在知道了PHP-FMP 全名叫做PHP-FASTCGI Process Manager之後,你可以理直氣壯的跟他們說no,並給他們普及一下這個知識點了。

php-fpm的行程包含master(常駐服務程式)與worker行程兩種

master程式
  • #master負責進程的調度(例如worker進程不夠的時候去fork一個子進程)
  • 負責監聽端口,一般是9000這個端口,可以在配置文件裡面設置,當然,還有另外一種方式,就是透過socket,可以透過netstat -nap | grep master的進程號 查看連接埠資訊(9000埠其實就是tcp的通訊方式,而socket是說的unix socket,從效率來說, unix socket顯然是最好的,因為它是進程之間的通信,但是unix socket要保證是在一台伺服器,如果是不同機器之間的通信,還是要使用tcp通信)

一文帶你深入剖析PHP-FMP

一文帶你深入剖析PHP-FMP

  • 接收來自伺服器的請求
work進度看名字就知道了,就是真正的打工階級,程式碼真正執行的地方

一文帶你深入剖析PHP-FMP

  • #再來看看php-fmp和nignx是怎麼通訊的
# #以socker通訊為栗子,nginx的conf檔案裡面,可以看到下面這段訊息

        location ~ [^/]\.php(/|$)
        {
            try_files $uri =404;
            fastcgi_pass  unix:/tmp/php-cgi.sock;
            fastcgi_index index.php;
            include fastcgi.conf;
        }

相信這段訊息大家都可以看明白,/tmp/php-cgi.sock 是php和nginx聯繫的橋樑,同時我們也看到了

include fastcgi.conf,我們來看一下

root@6d05153a8988:/usr/local/nginx/conf# cat fastcgi.conf

fastcgi_param  SCRIPT_FILENAME    $document_root$fastcgi_script_name;
fastcgi_param  QUERY_STRING       $query_string;
fastcgi_param  REQUEST_METHOD     $request_method;
fastcgi_param  CONTENT_TYPE       $content_type;
fastcgi_param  CONTENT_LENGTH     $content_length;

fastcgi_param  SCRIPT_NAME        $fastcgi_script_name;
fastcgi_param  REQUEST_URI        $request_uri;
fastcgi_param  DOCUMENT_URI       $document_uri;
fastcgi_param  DOCUMENT_ROOT      $document_root;
fastcgi_param  SERVER_PROTOCOL    $server_protocol;
fastcgi_param  REQUEST_SCHEME     $scheme;
fastcgi_param  HTTPS              $https if_not_empty;

fastcgi_param  GATEWAY_INTERFACE  CGI/1.1;
fastcgi_param  SERVER_SOFTWARE    nginx/$nginx_version;

fastcgi_param  REMOTE_ADDR        $remote_addr;
fastcgi_param  REMOTE_PORT        $remote_port;
fastcgi_param  SERVER_ADDR        $server_addr;
fastcgi_param  SERVER_PORT        $server_port;
fastcgi_param  SERVER_NAME        $server_name;

# PHP only, required if PHP was built with --enable-force-cgi-redirect
fastcgi_param  REDIRECT_STATUS    200;
fastcgi_param PHP_ADMIN_VALUE "open_basedir=NULL";

我們看到了一些熟悉的,比如REMOTE_ADDR,REQUEST_URI,現在你應該明白了,我們通過$_SERVER取得到的資訊就是這個設定檔裡面指定的

我們再來看看php-fmp的設定檔(請注意看裡面的註釋,我不做解釋了)

root@6d05153a8988:/usr/local/php/etc# cat php-fpm.conf
[global]
pid = /usr/local/php/var/run/php-fpm.pid
error_log = /usr/local/php/var/log/php-fpm.log
log_level = notice

[www]
listen = /tmp/php-cgi.sock
listen.backlog = -1
listen.allowed_clients = 127.0.0.1
listen.owner = www
listen.group = www
listen.mode = 0666
user = www
group = www
# 如何控制子进程,选项有static和dynamic
#区别:
#如果dm设置为 static,那么其实只有pm.max_children这个参数生效。系统会开#启设置数量的php-fpm进程。
#如果dm设置为 dynamic,那么pm.max_children参数失效,后面3个参数生效。
#系统会在php-fpm运行开始 的时候启动pm.start_servers个php-fpm进程,
#然后根据系统的需求动态在pm.min_spare_servers和pm.max_spare_servers之#间调整php-fpm进程数。
pm = dynamic
# 静态方式下开启的php-fpm进程数量
pm.max_children = 20
# 动态方式下的起始php-fpm进程数量
pm.start_servers = 10
# 动态方式下的最小php-fpm进程数
pm.min_spare_servers = 10
# 动态方式下的最大php-fpm进程数量
pm.max_spare_servers = 20
# php-fpm子进程能处理的最大请求数
pm.max_requests = 1024
pm.process_idle_timeout = 10s
request_terminate_timeout = 100
request_slowlog_timeout = 0
slowlog = var/log/slow.log

    關於php-fpm 的相關操作
INT, TERM QUIT 平滑終止 USR1 重新開啟日誌文件 USR2 平滑重載所有worker進程並重新載入配置和二進位模組

启动: /usr/local/php/sbin/php-fpm查看进程数: ps aux | grep -c php-fpm查看mater进程号:ps aux|grep 'php-fpm: master'|grep -v grep|awk '{print $2}' 或者cat /usr/local/php/var/run/php-fpm.pid

# 强制关闭
pkill php-fpm

kill -INT `cat /usr/local/php/var/run/php-fpm.pid` 
kill -INT [pid]

# 平滑重启 其实就是通过创建新的进程使 php.ini 生效
kill -USR2 `cat /usr/local/php/var/run/php-fpm.pid`
kill -USR2 [pid]
小结

至此,php-fpm 算是说完了,其实通过上面的解说,大家也会明白一个问题,为什么lnmp 承受的并发比lamp高,除了nginx的高性能之外,php-fpm 是不是也是其中的一个原因呢?

推荐学习:《PHP视频教程

以上是一文帶你深入剖析PHP-FMP的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:juejin.cn。如有侵權,請聯絡admin@php.cn刪除