為何有些團(tuán)隊(duì)更傾向于使用Go語(yǔ)言,而有些選擇PHP?
PHP的運(yùn)行原理
目前常見(jiàn)的 4 種 PHP 運(yùn)行模式
CGI 通用網(wǎng)關(guān)接口模式
FAST-CGI 模式
CLI 命令行模式
模塊模式
1. CGI 通用網(wǎng)關(guān)接口模式
每有一個(gè)用戶請(qǐng)求,都會(huì)先要?jiǎng)?chuàng)建 cgi 的子進(jìn)程,然后處理請(qǐng)求,處理完后結(jié)束這個(gè)子進(jìn)程。
cgi 是一種為了保證 web server 傳遞過(guò)來(lái)的數(shù)據(jù)是標(biāo)準(zhǔn)格式的通用網(wǎng)關(guān)接口協(xié)議。
2. FAST-CGI 模式
這個(gè)是 cgi 的升級(jí)版本,F(xiàn)astCGI 像是一個(gè)常駐 (long-live) 型的 CGI,它可以一直執(zhí)行著,只要激活后,不會(huì)每次都要花費(fèi)時(shí)間去 fork 一次,也是一種協(xié)議。
FastCGI 的工作原理是:
1)、Web Server 啟動(dòng)時(shí)載入 FastCGI 進(jìn)程管理器【PHP 的 FastCGI 進(jìn)程管理器是 PHP-FPM (php-FastCGI Process Manager)】(IIS ISAPI 或 Apache Module);
2)、FastCGI 進(jìn)程管理器自身初始化,啟動(dòng)多個(gè) CGI 解釋器進(jìn)程 (在任務(wù)管理器中可見(jiàn)多個(gè) php-cgi.exe) 并等待來(lái)自 Web Server 的連接。
3)、當(dāng)客戶端請(qǐng)求到達(dá) Web Server 時(shí),F(xiàn)astCGI 進(jìn)程管理器選擇并連接到一個(gè) CGI 解釋器。Web server 將 CGI 環(huán)境變量和標(biāo)準(zhǔn)輸入發(fā)送到 FastCGI 子進(jìn)程 php-cgi。
4)、FastCGI 子進(jìn)程完成處理后將標(biāo)準(zhǔn)輸出和錯(cuò)誤信息從同一連接返回 Web Server。當(dāng) FastCGI 子進(jìn)程關(guān)閉連接時(shí),請(qǐng)求便告處理完成。FastCGI 子進(jìn)程接著等待并處理來(lái)自 FastCGI 進(jìn)程管理器(運(yùn)行在 WebServer 中)的下一個(gè)連接。在正常的 CGI 模式中,php-cgi.exe 在此便退出了。
在 CGI 模式中,可以想象 CGI 通常有多慢。每一個(gè) Web 請(qǐng)求 PHP 都必須重新解析 php.ini、重新載入全部 dll 擴(kuò)展并重初始化全部數(shù)據(jù)結(jié)構(gòu)。使用 FastCGI,所有這些都只在進(jìn)程啟動(dòng)時(shí)發(fā)生一次。一個(gè)額外的好處是,持續(xù)數(shù)據(jù)庫(kù)連接 (Persistent database connection) 可以工作。
3.CLI 命令行模式
一般使用調(diào)用腳本、查看 php 信息時(shí)會(huì)使用到該模式
php -r”phpinfo ();” |less 分頁(yè)顯示
4. 模塊模式
Apache + mod_php
lighttp + spawn-fcgi
nginx + PHP-FPM
運(yùn)行原理
PHP-CGI:fast-cgi 是一種協(xié)議,而 php-cgi 是實(shí)現(xiàn)了這種協(xié)議的進(jìn)程。不過(guò)這種實(shí)現(xiàn)比較爛。它是單進(jìn)程的,一個(gè)進(jìn)程處理一個(gè)請(qǐng)求,處理結(jié)束后進(jìn)程就銷(xiāo)毀。
PHP-FPM:是對(duì) php-cgi 的改進(jìn)版,它直接管理多個(gè) php-cgi 進(jìn)程 / 線程。也就是說(shuō),php-fpm 是 php-cgi 的進(jìn)程管理器因此它也算是 fastcgi 協(xié)議的實(shí)現(xiàn)。
php 的運(yùn)行原理,就是在服務(wù)器啟動(dòng)時(shí),自動(dòng)載入 PHP-FPM 進(jìn)程管理器,從而管理多個(gè) PHP-CGI 進(jìn)程來(lái)準(zhǔn)備響應(yīng)用戶的。Linux下php-fpm進(jìn)程過(guò)多導(dǎo)致內(nèi)存耗盡問(wèn)題解決
請(qǐng)求,如下圖所示:
多個(gè)運(yùn)行模式相當(dāng)于超市的不同入口,運(yùn)行原理就是進(jìn)入超市后的固定的行走路線,通過(guò)不同的運(yùn)行模式進(jìn)入到底層。
教你用PHP爬取王者榮耀英雄皮膚高清壁紙(附源碼和壁紙)
Go語(yǔ)言的運(yùn)行原理
golang 是先編譯為靜態(tài)二進(jìn)制可執(zhí)行文件,再去運(yùn)行的。
1. go run 的執(zhí)行過(guò)程
1 .go run 的執(zhí)行過(guò)程,如圖所示
創(chuàng)建了兩個(gè)臨時(shí)文件夾 b001 和 exe
先執(zhí)行了 compile 命令,然后 link,生成了歸檔文件.a 和 最終可執(zhí)行文件
最終的可執(zhí)行文件放在 exe 文件夾里面。
命令的最后一步就是執(zhí)行了可執(zhí)行文件。
舉個(gè)例子,生成的臨時(shí)文件可以用 go run -work 看到,比如當(dāng)前生成的臨時(shí)文件夾是如下的路徑:
localhost:hello ruby$ go run -work mytest.go
WORK=/var/folders/kt/nlhsnpgn6lgd_q16f8j83sbh0000gn/T/go-build593750496
HelloWorld
你好,Go!!!
localhost:hello ruby$
進(jìn)入:/var/folders/kt/nlhsnpgn6lgd_q16f8j83sbh0000gn/T/go-build593750496 目錄,可以看到如下目錄結(jié)構(gòu):
可以看到,最終 go run 命令是生成了 2 個(gè)文件,一個(gè)是歸檔文件,一個(gè)是可執(zhí)行文件。
go run 命令在第二次執(zhí)行的時(shí)候,如果發(fā)現(xiàn)導(dǎo)入的代碼包沒(méi)有發(fā)生變化,那么 go run 不會(huì)再次編譯這個(gè)導(dǎo)入的代碼包。直接靜態(tài)鏈接進(jìn)來(lái)。
2023年P(guān)HP/Go面試題集總結(jié)【建議收藏】
2. go build 的執(zhí)行過(guò)程
go build 的執(zhí)行過(guò)程,如下圖所示
go build 用于編譯我們指定的源碼文件或代碼包以及它們的依賴包。但是注意如果用來(lái)編譯非命令源碼文件,即庫(kù)源碼文件,go build 執(zhí)行完是不會(huì)產(chǎn)生任何結(jié)果的。
這種情況下,go build 命令只是檢查庫(kù)源碼文件的有效性,只會(huì)做檢查性的編譯,而不會(huì)輸出任何結(jié)果文件。
go build 編譯命令源碼文件,則會(huì)在該命令的執(zhí)行目錄中生成一個(gè)可執(zhí)行文件,上面的例子也印證了這個(gè)過(guò)程。
go build 后面不追加目錄路徑的話,它就把當(dāng)前目錄作為代碼包并進(jìn)行編譯。go build 命令后面如果跟了代碼包導(dǎo)入路徑作為參數(shù),那么該代碼包及其依賴都會(huì)被編譯。
go build 命令究竟做了些什么呢?我們可以執(zhí)行 - n 這個(gè)命令來(lái)查看。 這里略過(guò)打印輸出。
執(zhí)行過(guò)程和 go run 大體相同,唯一不同的就是在最后一步,go run 是執(zhí)行了可執(zhí)行文件,但是 go build 命令,只是把庫(kù)源碼文件編譯了一遍,然后把可執(zhí)行文件移動(dòng)到了當(dāng)前目錄的文件夾中。
面試題解析
面試官:看你簡(jiǎn)歷里也有用過(guò) Go,Go 和 PHP 在運(yùn)行的時(shí)候有什么區(qū)別和優(yōu)勢(shì)?
回答:PHP 每個(gè)請(qǐng)求進(jìn)來(lái)時(shí)都會(huì)創(chuàng)建 fpm-worker 進(jìn)程,從而導(dǎo)致系統(tǒng)并發(fā)高時(shí) CPU 會(huì)產(chǎn)生頻繁創(chuàng)建進(jìn)程的開(kāi)銷(xiāo),而 Go 不會(huì)。
解析:PHP 每個(gè)請(qǐng)求進(jìn)來(lái)時(shí)都會(huì)創(chuàng)建 fpm-worker 進(jìn)程,這里 php 請(qǐng)求進(jìn)來(lái)就會(huì)由PHP - FPM(php-fpm 是 php-cgi 的進(jìn)程管理器)創(chuàng)建一個(gè) PHP-CGI 進(jìn)程來(lái)準(zhǔn)備響應(yīng)用戶的請(qǐng)求。而 go不會(huì),golang 是先編譯,后執(zhí)行。具體過(guò)程如圖
作為多年 PHP 的開(kāi)發(fā)者,在使用了 Go 語(yǔ)言之后......
作者:碼農(nóng)編程進(jìn)階筆記
歡迎關(guān)注微信公眾號(hào) :碼農(nóng)編程進(jìn)階筆記