動手復現http錯誤碼場景:499,500,502,504
動手復現http錯誤碼場景:499,500,502,504
關注微信公眾號:nginx,一起交流後端技術知識。
Status Code 499、500、502、504
也是後端Http
服務經常返回的狀態碼,試想一下,對於每個狀態碼,如果你能通過一些修改或配置來人為復現它,是不是會更利於你去掌握它呢?本文就是通過動手復現的方式來學習它們。
502,504
在超時的場景下會比較像,經常有人不能區分它們。499
產生的原因也常常會和504
會有內在的關聯,你都瞭解嗎?本文不光復現它們,而且會循序漸進,在對比之中復現它們。
下面所有復現的場景,修改nginx或者php-fpm的配置後,記得要重新啟動。
一、復現環境說明
系統環境和軟體環境為:Linux,Nginx,php-fpm
。
再來介紹一下本文復現會用到的Nginx
和php-fpm
的幾個配置。
#nginx超時相關配置:
fastcgi_connect_timeout 5; # nginx連線fastcgi的超時時間
fastcgi_send_timeout 10; #nginx往fastcgi傳送引數的超時時間
fastcgi_read_timeout 10; #nginx從fastcig獲取資料的超時時間
php-fpm配置:
; The timeout for serving a single request after which the worker process will ; be killed. This option should be used when the 'max_execution_time' ini option ; does not stop script execution for some reason. A value of '0' means 'off'. ; Available units: s(econds)(default), m(inutes), h(ours), or d(ays) ; Default Value: 0 ; 翻譯過來就是指一次請求的最長執行時間 request_terminate_timeout = 30s
所有復現場景都是在nginx
根目錄下建立一個hello.php
檔案,然後通過訪問http://127.0.0.1/hello.php
來檢視http
響應code
,hello.php
程式碼如下:
<?php
sleep(7); // 通過調整sleep秒數,來達成不同的復現
echo 'hello world';
?>
下面來逐一復現這些狀態碼的產生場景。
二、502
定義
502
,Bad Gateway
,閘道器錯誤,它往往表示閘道器從上游伺服器中接收到的響應是無效的。
先來了解一下閘道器是什麼含義,從巨集觀定義上來說只要連線兩個不同的網路的裝置都可以叫閘道器,其實具體到應用層Http
nginx
,nginx
負責把請求轉交給fastcgi
(即php-fpm
)進行處理,那麼在這個場景中Nginx
就是閘道器。
502
並不是指閘道器本身出了問題,而是從上游接收響應出了問題,比如由於上游服務自身超時導致不能產生響應資料,或者上游不按照協議約定來返回資料導致閘道器不能正常解析。
復現路徑1
關閉php-fpm
程序,返回502
。
這個比較容易理解,參照上面的定義,因為php-fpm
程序關閉,nginx
連線不上php-fpm
,即nginx
不能收從上層接收到響應資料。
nginx
錯誤日誌如下:
connect() to unix:/home/work/server/php-cgi.sock failed (2: No such file or directory) while connecting to upstream
復現路徑2
啟動php-fpm
程序,修改php-fpm.conf
的request_terminate_timeout
和php
程式碼的sleep
時間來複現。
php程式碼:
<?php
sleep(7);
echo 'hello world';
?>
php-fpm.conf配置:
request_terminate_timeout=5
nginx配置:
fastcgi_read_timeout 10;
php-fpm.conf
設定的最大執行時間是5s,但是php
指令碼需要的執行時間大於7s,所以php-fpm
程序執行5s時就回退出,此時php
指令碼沒有正常執行完成,所以返回給閘道器Nginx
的資料異常,於是導致502
。
php-fpm
錯誤日誌如下:
script '/home/work/webroot/hello.php' (request: "GET /hello.php") execution timed out (5.161544 sec), terminating
nginx
錯誤日誌如下:
recv() failed (104: Connection reset by peer) while reading response header from upstream
504
定義
504
,Gateway Timeout
,閘道器超時。
它表示閘道器沒有從上游及時獲取響應資料。注意它和502
在超時場景下的區別,502
是指上游php-fpm
因為超過自身允許的執行時間而不能正常生成響應資料,而504
是指在php-fpm
還未執行完成的某一時刻,由於超過了nginx
自身的超時時間,nginx
則以為上游php-fpm
沒有按照設定時間返回響應資料就會返回504
, 此時對於php-fpm
而言還會繼續執行下去,直到執行完成。
復現路徑
php
程式碼
<?php
sleep(7);
echo 'hello world';
error_log("hello", 3, "/tmp/hello.log");
?>
php-fpm.conf
配置:
request_terminate_timeout=30
nginx
配置:
fastcgi_read_timeout 5;
hello.php
指令碼執行時間需要7s,遠小於php-fpm
的一次請求的最大請求時間30s,所以php
指令碼可以正常完成執行,這個可以檢視/tmp/hello.log
檔案內容來得到證明。
由於nginx
從php-fpm
讀取資料的超時時間為5s,所以在5s的時科,nginx
還未從php-fpm
獲取到響應資料,於是返回504
。
nginx
錯誤日誌如下:
upstream timed out (110: Connection timed out) while reading response header from upstream
499
定義
499
, Client Closed Request
, 客戶端主動斷開連線。
是指一次http請求在客戶端指定的時間內沒有返回響應,此時,客戶端會主動斷開連線,此時表象為客戶端無響應返回,而nginx
的日誌中會status code
為499
。
此狀態碼在瀏覽器請求時幾乎不可見,因為瀏覽器預設的超時時間會很長。多見於服務之間的呼叫,在業務架構中常常會分層設計,拆分為不同的子系統或者微服務,這樣系統之間就會常常通過http
方式來請求,並且會設定每次請求的超時時間,當請求在請求時間內所呼叫的上游服務無返回,則會主動關閉連線,上游服務日誌中會記錄一條499
。
復現路徑
我們用上面504
復現時相同的程式碼和配置。
php
程式碼
<?php
sleep(7);
echo 'hello world';
error_log("hello", 3, "/tmp/hello.log");
?>
php-fpm.conf
配置:
request_terminate_timeout=30
nginx
配置:
fastcgi_read_timeout 5;
我們在linux
終端使用curl
命令來請求,-m
表示超時時間,單位為秒
curl -i -m 3 http://127.0.0.1/hello.php
返回為:
curl: (28) Operation timed out after 3004 milliseconds with 0 bytes received
nginx
的access
日誌的code
為499
,如下:
"HEAD /hello.php HTTP/1.1" 499 0
500
定義
500
, Internal Server Error
, 伺服器內部錯誤,伺服器遇到了一個未曾預料的狀況,導致了它無法完成對請求的處理。
日常開發中500
錯誤幾乎都是由於php
指令碼語法出現錯誤導致php-fpm
無法正常執行。
復現路徑
php
程式碼:
<?php
echo 'hello '
echo ' world';
?>
由於php
程式碼語法錯誤,php-fpm
執行失敗,然後告訴nginx
這一結果,nginx
則返回500
。
php
錯誤日誌:
PHP Parse error: syntax error, unexpected 'echo' (T_ECHO), expecting ',' or ';' in /home/work/webroot/hello.php on line 3
總結
-
499
是由於超過客戶端設定的請求超時時間,客戶端主動關閉連線,伺服器code
為499
。 -
500
多是由於程式碼語法錯誤,導致CGI
執行錯誤並且會把錯誤結果通知伺服器,伺服器則報500
。 -
502
是由於CGI
由於在自身的執行時間要求內無法按時完成,則無法返回給伺服器正常響應,此時伺服器會返回502
。 -
504
是CGI
在伺服器設定的超時時間內無法按時返回響應,伺服器則返回504
。 -
499,502,504
都會因為超時而產生,區別是超時超了誰的時,499
是超了客戶端本身的連線時間,502
是超了CGI
的執行時間,504
是超了伺服器本身的最大允許讀取時間。