1. 程式人生 > >動手復現http錯誤碼場景:499,500,502,504

動手復現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

再來介紹一下本文復現會用到的Nginxphp-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響應codehello.php程式碼如下:

<?php

sleep(7);  // 通過調整sleep秒數,來達成不同的復現

echo 'hello world';

?>

下面來逐一復現這些狀態碼的產生場景。

二、502

定義

502Bad Gateway,閘道器錯誤,它往往表示閘道器從上游伺服器中接收到的響應是無效的。

先來了解一下閘道器是什麼含義,從巨集觀定義上來說只要連線兩個不同的網路的裝置都可以叫閘道器,其實具體到應用層Http

請求這一領域,閘道器就是指是轉發其他伺服器通訊資料的伺服器,對於本文的復現環境而言,當客戶端請求資料到達nginxnginx負責把請求轉交給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.confrequest_terminate_timeoutphp程式碼的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

定義

504Gateway 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檔案內容來得到證明。

由於nginxphp-fpm讀取資料的超時時間為5s,所以在5s的時科,nginx還未從php-fpm獲取到響應資料,於是返回504

nginx錯誤日誌如下:

upstream timed out (110: Connection timed out) while reading response header from upstream

499

定義

499Client 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

nginxaccess日誌的code499,如下:

"HEAD /hello.php HTTP/1.1" 499 0 

500

定義

500Internal 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是由於超過客戶端設定的請求超時時間,客戶端主動關閉連線,伺服器code499

  • 500多是由於程式碼語法錯誤,導致CGI執行錯誤並且會把錯誤結果通知伺服器,伺服器則報500

  • 502是由於CGI由於在自身的執行時間要求內無法按時完成,則無法返回給伺服器正常響應,此時伺服器會返回502

  • 504CGI在伺服器設定的超時時間內無法按時返回響應,伺服器則返回504

  • 499,502,504都會因為超時而產生,區別是超時超了誰的時,499是超了客戶端本身的連線時間,502是超了CGI的執行時間,504是超了伺服器本身的最大允許讀取時間。