1. 程式人生 > >php 502 bad gateway 解決方法

php 502 bad gateway 解決方法

起因

新裝的LNMP環境怎麼都跑不起來程式碼,一直提示502 bad gateway 本著有事找度孃的精神,我首先百度了以下,果然度娘一下幫我找到了很多網友們提供的答案,五花八門,有的說是超時時間的問題,有的說是php沒有啟動的問題。
作為一個程式設計師排查問題是必備技能之一,經過一番排查,並不是超時的問題,php也已經正常啟動,那為什麼會出現這樣的問題呢?從php未啟動的基礎上我作了一個大膽的假設是不是配置的fast_cgi有問題呢?既然有了大膽的假設接下來就是小心求證的過程了。

小心求證

首先上一段為關於fast_cgi的配置程式碼

location ~* \.php$ 
{ fastcgi_index index.php; fastcgi_pass 127.0.0.1:9000; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param SCRIPT_NAME $fastcgi_script_name; }

乍看是沒什麼毛病畢竟網上千篇一律的都是這樣的配置,接下我使用netstat -tlnp | grep 9000 篩選了一下監聽9000的程式然而結果卻出乎意料,並沒有監聽9000的程式,結果如下

(Not all processes could be identified, non-owned process info

到這裡幾乎已經很大機率是出現在配置上了,查詢了一下NGINX 相關的配置資料發現
Nginx和PHP-FPM的程序間通訊有兩種方式,一種是TCP,一種是UNIX Domain Socket.
其中TCP是IP加埠,可以跨伺服器.而UNIX Domain Socket不經過網路,只能用於Nginx跟PHP-FPM都在同一伺服器的場景.用哪種取決於你的PHP-FPM配置:
方式1:
php-fpm.conf: listen = 127.0.0.1:9000
nginx.conf: fastcgi_pass 127.0.0.1:9000;
方式2:
php-fpm.conf: listen = /tmp/php-fpm.sock
nginx.conf: fastcgi_pass unix:/tmp/php-fpm.sock;
其中php-fpm.sock是一個檔案,由php-fpm生成,型別是srw-rw—-.

UNIX Domain Socket可用於兩個沒有親緣關係的程序,是目前廣泛使用的IPC機制,比如X Window伺服器和GUI程式之間就是通過UNIX Domain Socket通訊的.這種通訊方式是發生在系統核心裡而不會在網路裡傳播.UNIX Domain Socket和長連線都能避免頻繁建立TCP短連線而導致TIME_WAIT連線過多的問題.對於程序間通訊的兩個程式,UNIX Domain Socket的流程不會走到TCP那層,直接以檔案形式,以stream socket通訊.如果是TCP Socket,則需要走到IP層,對於非同一臺伺服器上,TCP Socket走的就更多了.

UNIX Domain Socket:
Nginx <=> socket <=> PHP-FPM
TCP Socket(本地迴環):
Nginx <=> socket <=> TCP/IP <=> socket <=> PHP-FPM
TCP Socket(Nginx和PHP-FPM位於不同伺服器):
Nginx <=> socket <=> TCP/IP <=> 物理層 <=> 路由器 <=> 物理層 <=> TCP/IP <=> socket <=> PHP-FPM
而此次出現問題的原因在於,我使用的是UNIX Domain Socket而nginx配置的確實tcp方式,既然知道癥結所在,修改起來也就方便很多了修改程式碼如下

location ~* \.php$ {
        fastcgi_index   index.php;
        #fastcgi_pass    127.0.0.1:9000; 註釋掉tcp方式
        fastcgi_pass    unix:/dev/shm/php-cgi.sock;#使用UNIX Domain Socket
        include           fastcgi_params;
        fastcgi_param   SCRIPT_FILENAME    $document_root$fastcgi_script_name;
        fastcgi_param   SCRIPT_NAME        $fastcgi_script_name;
    }

修改完配置之後,重啟伺服器,問題果然就解決了.