@author
汪春波(www.shxdledu.cn)
分享:[分享] 大環境下瑟瑟發抖辭職的第二天,拿了兩個 offer
- 看你簡歷裡也有用過 Go,Go 和 PHP 在執行的時候有什麼區別和優勢?
題主原回答:
PHP 每個請求進來時都會建立 fpm-worker 程式,從而導致系統併發高時 CPU 會產生頻繁建立程式的開銷,而 Go 不會。
解析回答:PHP 每個請求進來時都會建立 fpm-worker 程式
補充下,這裡php 請求進來就會 由PHP - FPM
(php-fpm是php-cgi的程式管理器)建立一個PHP-CGI程式來準備響應使用者的請求。具體過程如圖,大家也可以繼續往下看詳細解析。
解析回答:而go不會
golang 是先編譯,後執行。 具體可以往下看詳細解析。
php 執行原理
目前常見的4種PHP執行模式
- CGI通用閘道器介面模式
- FAST-CGI模式
- CLI命令列模式
- 模組模式
CGI通用閘道器介面模式
每有一個使用者請求,都會先要建立cgi的子程式,然後處理請求,處理完後結束這個子程式
cgi是一種為了保證web server傳遞過來的資料是標準格式的通用閘道器介面協議
比較老,比較原始,大多已經不用了
FAST-CGI模式
是cgi的升級版本,FastCGI 像是一個常駐 (long-live) 型的 CGI,它可以一直執行著,只要啟用後,不會每次都要花費時間去fork 一次,也是一種協議
FastCGI的工作原理是:
(1)、Web Server啟動時載入FastCGI程式管理器【PHP的FastCGI程式管理器是PHP-FPM(php-FastCGI Process Manager)】(IIS ISAPI或Apache Module);
(2)、FastCGI程式管理器自身初始化,啟動多個CGI直譯器程式 (在工作管理員中可見多個php-cgi.exe)並等待來自Web Server的連線。
(3)、當客戶端請求到達Web Server時,FastCGI程式管理器選擇並連線到一個CGI直譯器。Web server將CGI環境變數和標準輸入傳送到FastCGI子程式php-cgi。
(4)、FastCGI子程式完成處理後將標準輸出和錯誤資訊從同一連線返回Web Server。當FastCGI子程式關閉連線時,請求便告處理完成。FastCGI子程式接著等待並處理來自FastCGI程式管理器(執行在 WebServer中)的下一個連線。在正常的CGI模式中,php-cgi.exe在此便退出了。
在CGI模式中,可以想象 CGI通常有多慢。每一個Web請求PHP都必須重新解析php.ini、重新載入全部dll擴充套件並重初始化全部資料結構。使用FastCGI,所有這些都只在程式啟動時發生一次。一個額外的好處是,持續資料庫連線(Persistent database connection)可以工作。
CLI命令列模式
一般使用呼叫指令碼、檢視php資訊時會使用到該模式
php -r”phpinfo();” |less 分頁顯示
模組模式
- Apache + mod_php
- lighttp + spawn-fcgi
- nginx + PHP-FPM
執行原理
PHP-CGI:fast-cgi是一種協議,而php-cgi是實現了這種協議的程式。不過這種實現比較爛。它是單程式的,一個程式處理一個請求,處理結束後程式就銷燬
PHP - FPM:是對php-cgi的改進版,它直接管理多個php-cgi程式/執行緒。也就是說,php-fpm是php-cgi的程式管理器因此它也算是fastcgi協議的實現
php的執行原理,就是在伺服器啟動時,自動載入PHP-FPM程式管理器,從而管理多個PHP-CGI程式來準備響應使用者的請求,如下圖所示:
由於php-cgi是隨伺服器啟動載入的,所以初始化變數只會發生一次
執行模式和執行原理的區別
多個執行模式相當於超市的不同入口,執行原理就是進入超市後的固定的行走路線,通過不同的執行模式進入到底層(進入超市)
golang 執行原理
golang 是先編譯為靜態二進位制可執行檔案,再去執行。
看看 go run 與 go build 的區別
go run 的執行過程
- 建立了兩個臨時資料夾 b001 和 exe
- 先執行了 compile 命令,然後 link,生成了歸檔檔案.a 和 最終可執行檔案
- 最終的可執行檔案放在 exe 資料夾裡面。
- 命令的最後一步就是執行了可執行檔案。
舉個例子,生成的臨時檔案可以用go run -work
看到,比如當前生成的臨時資料夾是如下的路徑:
localhost:hello ruby$ go run -work mytest.go
WORK=/var/folders/kt/nlhsnpgn6lgd_q16f8j83sbh0000gn/T/go-build593750496
HelloWorld
你好,Go!!!
localhost:hello ruby$
我們進入:/var/folders/kt/nlhsnpgn6lgd_q16f8j83sbh0000gn/T/go-build593750496
目錄,可以看到如下目錄結構:
可以看到,最終go run
命令是生成了2個檔案,一個是歸檔檔案,一個是可執行檔案。
go run 命令在第二次執行的時候,如果發現匯入的程式碼包沒有發生變化,那麼 go run 不會再次編譯這個匯入的程式碼包。直接靜態連結進來。
go build 的執行過程
go build 用於編譯我們指定的原始碼檔案或程式碼包以及它們的依賴包。但是注意如果用來編譯非命令原始碼檔案,即庫原始碼檔案,go build 執行完是不會產生任何結果的。這種情況下,go build 命令只是檢查庫原始碼檔案的有效性,只會做檢查性的編譯,而不會輸出任何結果檔案。
go build 編譯命令原始碼檔案,則會在該命令的執行目錄中生成一個可執行檔案,上面的例子也印證了這個過程。
go build 後面不追加目錄路徑的話,它就把當前目錄作為程式碼包並進行編譯。go build 命令後面如果跟了程式碼包匯入路徑作為引數,那麼該程式碼包及其依賴都會被編譯。
go build 命令究竟做了些什麼呢?我們可以執行-n這個命令來檢視。 這裡略過列印輸出。
執行過程和 go run 大體相同,唯一不同的就是在最後一步,go run 是執行了可執行檔案,但是 go build 命令,只是把庫原始碼檔案編譯了一遍,然後把可執行檔案移動到了當前目錄的資料夾中。
總結一下如下圖:
本作品採用《CC 協議》,轉載必須註明作者和本文連結