首頁 運維 Nginx nginx+php-fpm服務HTTP狀態碼502怎麼解決

nginx+php-fpm服務HTTP狀態碼502怎麼解決

May 21, 2023 am 08:07 AM
php nginx fpm

我們的一個web項目,由於新上城市增多,導致訪問量增大,db壓力增大,作為提供接口的業務方,最近被下游反饋大量請求“502”。

502,bad gateway,通常都是upstream(這裡就是php)出錯,對於php,造成502的原因常見的就是腳本執行超過timeout設定時間,或是timeout設定過大,導致php進程長時間不能被釋放,沒有空閒worker進程來接客。

我們的專案就是php執行時間設定過短導致的,對於這種情況,可以先適當增大php的執行時間,先保證清除502,優化的事情畢竟要花更多的時間。

控制php執行時間的選項有兩個,在php.ini中max_execution_time 和php-fpm中request_terminate_timeout,其中request_terminate_timeout 可以覆寫max_execution_time,所以如果不想改全域的php.ini,那隻改php- fpm的配置就可以了。

下邊我就來詳細的分析為什麼php腳本執行超出設定時間會導致nginx回傳502。

先來佈景,讓問題重現:

nginx和php分別只啟動一個worker,方便追蹤。

php-fpm的request_terminate_timeout設定為3s。

測試腳本test.php

sleep(20);
echo 'ok';
登入後複製

go go go:

#在瀏覽器存取www.v.com/test.php,3s後如期出現...404 ? ? ? what? ? ?

nginx+php-fpm服務HTTP狀態碼502怎麼解決

出師不利啊,趕緊看看nginx的設定檔

nginx+php-fpm服務HTTP狀態碼502怎麼解決

這個location設定是當發生5xx錯誤時跳到一個好看點的介面,但是我在/usr/share/nginx/html下並沒有50x.html這個檔案。所以搞了個404出來。這不是很影響我判斷問題的準確度?直接註解掉!再次訪問,等待3s,終於'正常'的介面出來了。

nginx+php-fpm服務HTTP狀態碼502怎麼解決

環境好了,下邊就上套路,按照web問題的排查套路走一遍,先看看錯誤日誌吧:

nginx:

nginx+php-fpm服務HTTP狀態碼502怎麼解決

報錯都是recv() failed (104: connection reset by peer。

recv時失敗了,連接被重置了。為啥連接被重置了?難道一言不合。

我們在看看php-fpm的錯誤日誌:

(注意php-fpm中php_admin_value[error_log]選項指定php的錯誤日誌,會覆寫php.ini中的。但這裡不是看php的錯誤,而是看php-fpm的錯誤。php-fpm的錯誤日誌由php-fpm.conf中的error_log選項指定。)

nginx+php-fpm服務HTTP狀態碼502怎麼解決

每一次請求都是產生2個warning和1個notice:

warning:腳本執行逾時了,終止了。

warning:子程序收到sigterm訊號退出了。

notice:啟動了一個新的子進程(因為我設定的pm.min_spare_servers = 1)

看來如果php的worker進程執行逾時,不僅終止腳本執行,而且worker進程也會退出。看來nginx的報錯連接被重置是因為php的worker進程退出了(在tcp連接中一方如果斷掉的話會發送rst給另一方)

通過日誌已經可以知道php腳本執行逾時,worker子程序退出,導致nginx報錯connection reset by peer,下邊我們透過strace來看看php和nginx的狀況:

php:

nginx+php-fpm服務HTTP狀態碼502怎麼解決

1.accept一個nginx的連接請求(socket,bind,listen都在master中完成),可以看到nginx的連接埠是47039,從fd0讀取數據,就是從標準輸入中,這個是fast-cgi協定規定的。accept之後的已連接描述符是3。

2.從fd3讀取nginx傳遞過來的數據,fastcgi協定格式,接收了856位元組。為什麼read5次呢?

因為fastcgi協定封包是8位元組對齊,由包頭和包體組成。而且都是會先發一個request封包,包含一些請求id,版本,typpe等資訊(包頭包體各佔8位元組),再發一個params封包,傳遞get參數和環境變數(包頭8位元組,包體變長),最後發送一個沒有包體只有包頭的params資料包,表示參數發送結束(包頭8位元組)。所以前3個read用來讀出request包的包頭和包體,還有params包的包頭,第四個read是讀取真正的數據,最後一個read是讀取最後一個params包的包頭。所以nginx傳遞的資料應該是8 8 8 856 8=896位元組(和下邊nginx的傳輸bytes能對應上)。注意如果是post方式,也會傳送stdin封包。

3.設定休眠20s,就是php程式中的sleep(20),之後因為行程終止了,所以後邊就沒囉。 strace程式也退出啦。

nginx:

nginx+php-fpm服務HTTP狀態碼502怎麼解決

1.accept到瀏覽器的請求,可以看到瀏覽器端的連接埠是56434,ip是192.168.1.105,已建立連接的fd是3。

2.從fd3接收數據,http協定。

3.建立一個socket,fd21,用於和php建立連線。

4.連接到fd21,可以看到連接的是本機的9000端口,這裡nginx和php-fpm使用ip socket連接方式,nginx和php-fpm部署在一台機器上可以考慮unix domain socket。

5.寫入fd21資料,fast-cgi協定格式,我們看到寫入的長度是896,和上邊的php接收的長度是對應的。

6.recvfrom函數從fd21傳回 econnreset (connection reset by peer)

7.向fd9中寫入錯誤訊息,可以推斷fd9就是nginx錯誤日誌的檔案描述子。

8.關閉和fd21的連線。

9.寫入fd3502 bad gateway,就是傳回瀏覽器的資訊。

10.向fd8寫入一條存取日誌,可以推論fd8就是nginx存取日誌的檔案描述子。

來驗證一下nginx存取日誌和錯誤日誌的推論。可以看到的確是fd8,fd9,並處於寫入模式。

nginx+php-fpm服務HTTP狀態碼502怎麼解決

那麼在這個過程中整個網路包的傳輸我們不妨也看一下:

透過tcpdump抓包,用神器看比較方便。

因為只想看nginx和php的通訊,在上邊又知道nginx的連接埠是47039,可以透過tcp.srcport==47039過濾出對應的套件。

nginx+php-fpm服務HTTP狀態碼502怎麼解決

可以看到nginx和php-fpm資料互動的過程:47039->9000建立三次握手,接著向9000發送數據,9000回覆ack,3s後9000回覆rst。沒毛病。

注意:

syn,fin各佔一個序號

ack,rst不佔序號(28,29兩個套件的reqnum和acknum都是相同的)

序號是每一位元組加1(29包發送896字節,同時29包seq為4219146879,30包的ack為4219147775,正好相差896)

rst不需要回覆。

以上是nginx+php-fpm服務HTTP狀態碼502怎麼解決的詳細內容。更多資訊請關注PHP中文網其他相關文章!

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

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
1 個月前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
1 個月前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
1 個月前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.聊天命令以及如何使用它們
1 個月前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

PHP:處理數據庫和服務器端邏輯 PHP:處理數據庫和服務器端邏輯 Apr 15, 2025 am 12:15 AM

PHP在數據庫操作和服務器端邏輯處理中使用MySQLi和PDO擴展進行數據庫交互,並通過會話管理等功能處理服務器端邏輯。 1)使用MySQLi或PDO連接數據庫,執行SQL查詢。 2)通過會話管理等功能處理HTTP請求和用戶狀態。 3)使用事務確保數據庫操作的原子性。 4)防止SQL注入,使用異常處理和關閉連接來調試。 5)通過索引和緩存優化性能,編寫可讀性高的代碼並進行錯誤處理。

怎麼查看nginx是否啟動 怎麼查看nginx是否啟動 Apr 14, 2025 pm 01:03 PM

確認 Nginx 是否啟動的方法:1. 使用命令行:systemctl status nginx(Linux/Unix)、netstat -ano | findstr 80(Windows);2. 檢查端口 80 是否開放;3. 查看系統日誌中 Nginx 啟動消息;4. 使用第三方工具,如 Nagios、Zabbix、Icinga。

linux怎麼啟動nginx linux怎麼啟動nginx Apr 14, 2025 pm 12:51 PM

在 Linux 中啟動 Nginx 的步驟:檢查 Nginx 是否已安裝。使用 systemctl start nginx 啟動 Nginx 服務。使用 systemctl enable nginx 啟用在系統啟動時自動啟動 Nginx。使用 systemctl status nginx 驗證啟動是否成功。在 Web 瀏覽器中訪問 http://localhost 查看默認歡迎頁面。

linux怎麼查看nginx是否啟動 linux怎麼查看nginx是否啟動 Apr 14, 2025 pm 12:48 PM

在 Linux 中,使用以下命令檢查 Nginx 是否已啟動:systemctl status nginx根據命令輸出進行判斷:如果顯示 "Active: active (running)",則 Nginx 已啟動。如果顯示 "Active: inactive (dead)",則 Nginx 已停止。

nginx在windows中怎麼配置 nginx在windows中怎麼配置 Apr 14, 2025 pm 12:57 PM

如何在 Windows 中配置 Nginx?安裝 Nginx 並創建虛擬主機配置。修改主配置文件並包含虛擬主機配置。啟動或重新加載 Nginx。測試配置並查看網站。選擇性啟用 SSL 並配置 SSL 證書。選擇性設置防火牆允許 80 和 443 端口流量。

PHP的目的:構建動態網站 PHP的目的:構建動態網站 Apr 15, 2025 am 12:18 AM

PHP用於構建動態網站,其核心功能包括:1.生成動態內容,通過與數據庫對接實時生成網頁;2.處理用戶交互和表單提交,驗證輸入並響應操作;3.管理會話和用戶認證,提供個性化體驗;4.優化性能和遵循最佳實踐,提升網站效率和安全性。

PHP和Python:代碼示例和比較 PHP和Python:代碼示例和比較 Apr 15, 2025 am 12:07 AM

PHP和Python各有優劣,選擇取決於項目需求和個人偏好。 1.PHP適合快速開發和維護大型Web應用。 2.Python在數據科學和機器學習領域佔據主導地位。

nginx403怎麼解決 nginx403怎麼解決 Apr 14, 2025 am 10:33 AM

如何解決 Nginx 403 Forbidden 錯誤?檢查文件或目錄權限;2. 檢查 .htaccess 文件;3. 檢查 Nginx 配置文件;4. 重啟 Nginx。其他可能原因還包括防火牆規則、SELinux 設置或應用程序問題。

See all articles