首頁  >  文章  >  後端開發  >  不是很理解PHP的運作機制,求解

不是很理解PHP的運作機制,求解

WBOY
WBOY原創
2016-08-04 09:20:121071瀏覽

像java、nodejs,應該都是在服務端持續運行的一個程序,這個程序會一直運行,會佔用cpu,會佔用內存,接到網絡請求,就會處理。

而PHP似乎不是一個程序,更類似於html,只有打開的時候才會執行,當沒有人訪問php的服務時,php甚至一點點內存都不佔,一點點cpu都不佔,是這樣嗎?


如果是這樣,那麼php不是很難封裝資料庫class?因為每個用戶進來都要給他開一個進程,進程之間互不相通,A用戶進來給他開一個數據庫連接,B用戶進來又要給他單獨開數據庫連接。那php不是在不斷連接、斷開資料庫?用戶多了之後,開銷應該很大吧?


這也是導致php沒有類似js的 setIntervalsetTimeout 函數的原因嗎?

回覆內容:

像java、nodejs,應該都是在服務端持續運行的一個程序,這個程序會一直運行,會佔用cpu,會佔用內存,接到網絡請求,就會處理。

而PHP似乎不是一個程序,更類似於html,只有打開的時候才會執行,當沒有人訪問php的服務時,php甚至一點點內存都不佔,一點點cpu都不佔,是這樣嗎?


如果是這樣,那麼php不是很難封裝資料庫class?因為每個用戶進來都要給他開一個進程,進程之間互不相通,A用戶進來給他開一個數據庫連接,B用戶進來又要給他單獨開數據庫連接。那php不是在不斷連接、斷開資料庫?用戶多了之後,開銷應該很大吧?


這也是導致php沒有類似js的 setIntervalsetTimeout 函數的原因嗎?

以PHP-FPM為例(類似Apache MOD_PHP)說說PHP的運作機制.
首先,PHP-FPM是一個C實現的多進程FastCGI服務.
每個PHP-FPM工作進程都內建了PHP解釋器,不依賴PHP-CGI,都支援後台常駐,例如設定:

<code>nginx.conf: 访问io.php的请求都交给监听9001的PHP-FPM进程池处理
location = /io.php {
    include fastcgi_params;
    fastcgi_pass 127.0.0.1:9001;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}

php-fpm: 正常脚本由静态www池处理,阻塞脚本由动态io池处理
[www]
;名为www的进程池监听9000端口,常驻进程数量为固定4个
listen = 127.0.0.1:9000
pm = static
pm.max_children = 4
[io]
;名为io的进程池监听9001端口,进程数常驻4个,最大8个
listen = 127.0.0.1:9001
pm = dynamic
pm.max_children = 8
pm.start_servers = 4
pm.min_spare_servers = 4
pm.max_spare_servers = 4</code>

PHP-FPM主進程就是用來管理這些工作進程的,比如一個工作進程被殺死了,立刻重建一個.
PHP-FPM提供給了pm.status_path來透過瀏覽器查看整套PHP-FPM服務的工作狀態.
像執行超時放棄,處理指定請求數後自動重啟工作進程,慢日誌記錄(找出耗時的檔案和函數)都支援.

而且開啟持久連接後,每個PHP-FPM工作進程都能保持一個到MySQL的長連接不釋放,避免重複連接數據庫.
比如下圖展示的是2個PHP-FPM進程跟MySQL建立的2個長連接:
不是很理解PHP的運作機制,求解
另外,針對Memcached和Redis的PECL擴充也都實現了持久連接的功能.

上面說了PHP-FPM的體系,下面就該說說PHP腳本在PHP-FPM體系下的生命週期.
PHP腳本裡的量(包括全局變數)的生命週期只存在於一次請求內,請求處理完成,PHP-FPM就自動釋放資源.
一次請求釋放一次資源,這種內存釋放是非常徹底的,PHP基於引用計數的GC甚至都還沒發揮作用程序就已經結束了.
這裡的釋放資源指的是腳本裡控制的資源,而不會幹預到PHP-FPM常駐進程,不會讓PHP-FPM進程關閉,也不能讓PHP-FPM關閉到MySQL的持久連接,PHP-FPM只負責輸入PHP腳本,執行PHP操作,如果加入了ZendOpcache支援,還可以把解析PHP腳本產生的opcode全部緩存到內存里共下次直接解釋執行.PHP7中還支持用opcache.file_cache導出腳本opcode實現源代碼保護.

PHP的一些常識:
資料庫連接池: PHP持久連接就是天然的透明的無需程序幹預的連接池,支持MySQL/Memcached/Redis等.
內存常駐: PHP-FPM進程,ZendOpcache緩存的腳本的opcode ,鳥哥開發的Yac都是內存常駐的.
垃圾回收: PHP-FPM一次請求釋放一次資源的運行模式,削弱了基於引用計數的GC的作用.

最後,CLI下工作的PHP守護程式服務例如Swoole/WorkerMan才跟Java/Node之類相似.

雖然我已經下班了,看到你這個提說PHP是類似html我忍不了。 PHP功能是html無法比擬的好不好,就拿你說的連接資料庫的範例來說,html能連接資料嗎?能讀取資料庫內容嗎?不能吧!還有你說多個用戶來訪問每個用戶都要開一個資料庫連接,你這樣太小看PHP了。封裝一個資料庫連接類別很簡單很簡單,這些我就不貼code了。 PHP手冊每種資料庫擴充都有介紹也有事例,可以自己做參考。你既然提到java那一定也知道單例模式吧! PHP封裝好一個資料庫連線類別設定單例模式就可以實現資料連線靜態化。不管多少用戶來訪問直接調用一下就可以不是你說的多個用戶來訪問就開多個進程。還有你提到的setIntervalsetTimeout不就是定時執行嗎! PHP也可以的啊!先定義好PHP要實現的功能,然後透過在伺服器上設定crontab就可以了,參數自己設定就行,或者還有php-fpm。還有等等等的功能我就不羅列了,也沒整理答案格式你先湊活著看。我得下班走人了,有問題咱明天繼續討論

總之,PHP是一門很好很好的語言,功能很強大……而且還在不斷的發展壯大中……易學易懂啊!兄弟

PHP不能常駐記憶體,每一個HTTP請求開後,連接資料庫,等請求結束了,資料庫連線 和 各種變數都釋放掉了。

你整體上的理解是對的,但的不是所有的語言都是java那種常駐記憶體的,python,go,c都不是。 PHP也確實沒有連結池的概念,進程執行完就好釋放掉,不會留著給其他進程用

給你 《深入理解 PHP 核心》第二章第一節的內容連結:

http://www.php-internals.com/...

你的疑惑,只是因為你只看到了表面。

如果你用過 swoole,我想你一定不會提出這種問題。

呃,你當php-fpm沒到。 。 。

而PHP似乎不是一個程序,更類似於html

PHP只是可以嵌入到HTML中,但跟HTML是天壤之別,PHP有很多擴充可以做不同的事情,HTML能嗎?

只有打開的時候才會執行,當沒有人訪問php的服務時,php甚至一點點內存都不佔,一點點cpu都不佔,是這樣嗎?

PHP主要有兩種運作方式(除了CLI):
1.Apache為代表的mod_php,這時工作是交給Apache處理了。
2.Nginx/Lighttpd用的php-fpm(fastcgi程式管理員),這個是常駐的守護程式。
所以說,怎麼可能不佔CPU和記憶體?

如果是這樣,那php不是很難封裝資料庫class?因為每個用戶進來都要給他開一個進程,進程之間互不相通,A用戶進來給他開一個數據庫連接,B用戶進來又要給他單獨開數據庫連接。那php不是在不斷連接、斷開資料庫?用戶多了之後,開銷應該很大吧?

以MySQL為例,如果連接時選擇pconnect(持久連接)的話,下次就會直接使用已存在的連接,不會關閉連接。
PDO也有長連接選項。

這也是導致php沒有類似js的setIntervalsetTimeout函數的原因嗎?

PHP是有延時函數(如sleep())的哦,而且精確度比JS的高太多太多了(微秒等級)。

好熱鬧。 @ivanilla 的回答與評論包含這麼多信息,感謝。

其實我認為針對樓主的問題,PHP的運作機制就是解釋執行腳本。 PHP是為中小型網站提供服務端支援的腳本語言,在開發速度與運行效率上具有良好的平衡,這是它成功的原因。

所以樓主的其它觀點就沒啥看頭了,連爭論都沒意義,如果PHP擁有了你想像的那些東西,這個語言也就沒人用了,大家乾脆還是用java好了。

樓主對PHP的一些基本知識不了解,應該是剛開始接觸PHP。簡單來說PHP可以以兩種模式運行,一種是腳本方式,如在shell 裡執行php xxx.php;一種是樓主理解的有網路請求才啟動運行(不是十分貼切),有編譯成apache的擴充方式,也有fast-cgi方式。 apache的mod_php方式就是來一個請求起一個行程執行,效率底下,對應的有各種參數最佳化等。而fast-cgi則要高效得多,具體的樓主可以翻看相應的手冊並實際操作一下。

樓上幾位真有耐心

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn