HTTP狀態碼面試必知


typora-root-url: ./HTTPCODE

HTTP狀態碼必知必會

這里主要介紹運維過程中經常遇到的狀態碼。並通過業界流行的Nginx進行模擬實現,讓大家能有一種所見即所得的感覺。希望大家通過此知識點的學習,能夠對HTTP狀態碼有一個理性的認識(如果你是一名運維人員,那么請記牢記些狀態碼的含義)。

實驗場景介紹

操作系統: CentOS 7.3
實驗用軟件包: nginx php-fpm php httpd-tools(使用了YUM倉庫原生軟件包)
yum -y install nginx php-fpm php httpd-tools

2XX狀態碼

2XX 類型的狀態碼表示一個HTTP請求成功。我們遇到的最典型2XX狀態碼為200,其他2XX狀態碼我在目前運維生涯中還未遇到。
200狀態碼
這個是一個大家都希望看到的狀態碼,表示一個HTTP請求得到了正確的響應。在此不做模擬測試。

3XX狀態碼

3XX 類型狀態碼主要表示HTTP請求URL重定向行為。常見的3XX狀態碼有301、302及304。
301狀態碼
URL 永久性重定向。在Nginx中通過rewrite 指令結合 permanent 標記實現。

測試用例

# cat 301.conf
server {
   listen       80;
   server_name test.qfedu.com;
   root         /usr/share/nginx/html;
   access_log   /var/log/nginx/test.qfedu.com-acess.log;
   error_log   /var/log/nginx/test.qfedu.com-error.log;

   rewrite ^(.*)$ /index.html permanent;

   location / {
       index  index.html index.htm;
  }
}

測試

# curl http://127.0.0.1/ -H "HOST: test.qfedu.com" -I
HTTP/1.1 301 Moved Permanently
Server: nginx/1.12.2
Date: Tue, 08 May 2018 17:02:26 GMT
Content-Type: text/html
Content-Length: 185
Location: http://test.qfedu.com/index.html
Connection: keep-alive
302狀態碼
URL 臨時重定向。在Nginx中通過rewrite 指令結合 redirect 標記實現。

測試用例

# cat 302.conf
server {
   listen       80;
   server_name test.qfedu.com;
   root         /usr/share/nginx/html;
   access_log   /var/log/nginx/test.qfedu.com-acess.log;
   error_log   /var/log/nginx/test.qfedu.com-error.log;

   rewrite ^(.*)$ /index.html redirect;

   location / {
       index  index.html index.htm;
  }
}

測試

# curl http://127.0.0.1/ -H "HOST: test.qfedu.com" -I
HTTP/1.1 302 Moved Temporarily
Server: nginx/1.12.2
Date: Tue, 08 May 2018 17:04:37 GMT
Content-Type: text/html
Content-Length: 161
Location: http://test.qfedu.com/index.html
Connection: keep-alive
301 VS 302
301和302狀態碼都是URL重定向。其中301永久重定向,302臨時重定向。不管是永久還是臨時,但對用戶而言這兩者沒有任何感官上的區別。都是在訪問連接A的時候跳轉到了連接B,並看到瀏覽器上的地址同樣由A變成了B。既然如此,那為什么還要同時存在301和302呢?
它們主要區別在於搜索引擎。搜索引擎是要建立索引規則和權重的,如果連接A被設定為永久重定向到連接B,那搜索引擎可以確定A的地址永久改變了,就會把B當做唯一有效的目標地址。這時搜索引擎會把老地址相關信息帶到新地址,同時在搜索引擎索引庫中徹底廢棄掉原先的老地址。而搜索引擎對於302則沒有這樣的行為。
304狀態碼
客戶端緩存。通過Nginx 中的 expires 指令完成。

測試用例

# cat 304.conf
server {
   listen       80;
   server_name test.qfedu.com;
   root         /usr/share/nginx/html;
   access_log   /var/log/nginx/test.qfedu.com-acess.log;
   error_log   /var/log/nginx/test.qfedu.com-error.log;

   location ~ .*\.(gif|jpg|jpeg|png|bmp|swf|html)$ {
       expires     1d;
  }
}

測試

將 test.qfedu.com 域名在本地的hosts文件中進行綁定。然后開瀏覽器進行測試。

第一次訪問測試

由於是第一次訪問,在瀏覽器的DEBUG模式下發現返回狀態碼是200。

 

第二次訪問測試

由於已經經過了一次訪問,客戶端已經將靜態資源信息換成到了本地。在第二次訪問時,確認本地資源沒有過期,返回狀態碼為304。說明使用了上一次請求時的響應資源。

 

4XX狀態碼

4XX 類型狀態碼主要表示客戶端錯誤。客戶端發起的HTTP請求頭不完整、客戶度使用的用戶名、密碼錯誤等等。都會被標示為客戶端錯誤。常見的4XX狀態碼有 400、401、403等。
400狀態碼
當WEB服務器遇到不完整的HTTP請求頭時,會返回400狀態碼。請求頭信息或者Cookie信息過大,通常是導致不完整的請求頭的原因。那多大的請求頭算過大呢? 這個值由WEB服務器端配置決定。
在Nginx 這類WEB服務器中,決定這個值的配置字段是large_client_header_buffers。 我們通過調小這個字段,來模擬400狀態碼。

測試用例

# cat 400.conf
server {
   listen       80;
   server_name test.qfedu.com;
   root         /usr/share/nginx/html;
   access_log   /var/log/nginx/test.qfedu.com-acess.log;
   error_log   /var/log/nginx/test.qfedu.com-error.log;

   # 此指令在NGINX的HTTP段和SERVER段都可以生效。
   # 若實驗室發現在SERVER段中不生效,可以在HTTP段中設置。
   large_client_header_buffers 1 1k;

   location / {
       index  index.html index.htm;
  }
}

測試

# 模式時,設置了一個遠超過1K的cookie頭部
# curl --cookie "user=sidisisidisidisisidisidisisidisidisisidisidisisidisidisisidisidisidisisidisisidisidisisidisidisisidisidisisidisidisisidisidisisidisidissidisisidisidisisidisidisisidisidisisidisidisisidisidisisidisidissidisisidisidisisidisidisisidisidisisidisidisisidisidisisidisidissidisisidisidisisidisidisisidisidisisidisidisisidisidisisidisidissidisisidisidisisidisidisisidisidisisidisidisisidisidisisisidisisidisidisisidisidisisidisidisisidisidisisidisidisisidisidisidisisidisisidisidisisidisidisisidisidisisidisidisisidisidisisidisidissidisisidisidisisidisidisisidisidisisidisidisisidisidisisidisidissidisisidisidisisidisidisisidisidisisidisidisisidisidisisidisidissidisisidisidisisidisidisisidisidisisidisidisisidisidisisidisidissidisisidisidisisidisidisisidisidisisidisidisisidisidisisisidisisidisidisisidisidisisidisidisisidisidisisidisidisisidisidisidisisidisisidisidisisidisidisisidisidisisidisidisisidisidisisidisidissidisisidisidisisidisidisisidisidisisidisidisisidisidisisidisidissidisisidisidisisidisidisisidisidisisidisidisisidisidisisidisidissidisisidisidisisidisidisisidisidisisidisidisisidisidisisidisidissidisisidisidisisidisidisisidisidisisidisidisisidisidisisisidisisidisidisisidisidisisidisidisisidisidisisidisidisisidisidisidisisidisisidisidisisidisidisisidisidisisidisidisisidisidisisidisidissidisisidisidisisidisidisisidisidisisidisidisisidisidisisidisidissidisisidisidisisidisidisisidisidisisidisidisisidisidisisidisidissidisisidisidisisidisidisisidisidisisidisidisisidisidisisidisidissidisisidisidisisidisidisisidisidisisidisidisisidisidisisisisisisisisisisisisisisisisisisisisisisisisisisisisisisisisisisisissisisisisisisisisisisisisisiisissiissisisisiissi" http://127.0.0.1/ -H "HOST: test.qfedu.com" -I
HTTP/1.1 400 Bad Request
Server: nginx/1.12.2
Date: Sun, 13 May 2018 14:35:53 GMT
Content-Type: text/html
Content-Length: 249
Connection: close
401狀態碼
權限驗證錯誤。就是需要用戶名、密碼等權限認證,但是客戶端又沒有通過認證。在Nginx中要想模擬這種狀態碼,必須將Nginx調整成認證模式。

測試用例

生產授權用戶名和密碼

# htpasswd -c /etc/passwd.db qfedu
New password:
Re-type new password:
Adding password for user qfedu

Nginx授權配置

# cat 401.conf
server {
  listen       80;
  server_name test.qfedu.com;
  root         /usr/share/nginx/html;
  access_log   /var/log/nginx/test.qfedu.com-acess.log;
  error_log   /var/log/nginx/test.qfedu.com-error.log;

  location / {
      auth_basic "secret";
      auth_basic_user_file /etc/passwd.db;
      index index.html index.htm;
  }
}

測試

將 test.qfedu.com 域名在本地的hosts文件中進行綁定。然后開瀏覽器進行測試。

在彈出的認證授權框中輸入正確的用戶名和密碼

 

在彈出的認證授權框中輸入錯誤的用戶名和密碼,並退出認證授權框

 

 

403狀態碼
沒有權限訪問。文件權限過小或者人為設置不允許某個IP地址訪問等,都會浮現403狀態碼。

測試用例1

# 將文件權限設置為最小
# ll /usr/share/nginx/html/index.html
-rw-r--r-- 1 root root 3700 3月   6 04:26 /usr/share/nginx/html/index.html
# chmod 0 /usr/share/nginx/html/index.html
# ll /usr/share/nginx/html/index.html
---------- 1 root root 3700 3月   6 04:26 /usr/share/nginx/html/index.html

Nginx配置文件

server {
   listen       80;
   server_name test.qfedu.com;
   root         /usr/share/nginx/html;
   access_log   /var/log/nginx/test.qfedu.com-acess.log;
   error_log   /var/log/nginx/test.qfedu.com-error.log;

   location / {
       index  index.html index.htm;
  }
}

測試

# curl http://127.0.0.1/index.html -H "HOST: test.qfedu.com" -I
HTTP/1.1 403 Forbidden
Server: nginx/1.12.2
Date: Sun, 13 May 2018 15:04:04 GMT
Content-Type: text/html
Content-Length: 169
Connection: keep-alive

測試用例2

# 不允許客戶端IP地址為127.0.0.1的用戶訪問。先確保上一步測試中的文件權限還原。
# chmod 644 /usr/share/nginx/html/index.html
# 測試已經可以正常訪問
# curl http://127.0.0.1/index.html -H "HOST: test.qfedu.com" -I

Nginx配置

# cat 401.conf
server {
   listen       80;
   server_name test.qfedu.com;
   root         /usr/share/nginx/html;
   access_log   /var/log/nginx/test.qfedu.com-acess.log;
   error_log   /var/log/nginx/test.qfedu.com-error.log;

   if ($remote_addr = "127.0.0.1") {
       return 403;
  }

   location / {
       index  index.html index.htm;
  }
}

測試

# curl http://127.0.0.1/index.html -H "HOST: test.qfedu.com" -I
HTTP/1.1 403 Forbidden
Server: nginx/1.12.2
Date: Sun, 13 May 2018 15:06:35 GMT
Content-Type: text/html
Content-Length: 169
Connection: keep-alive
404狀態碼
文件不存在。當我們訪問一個不存在的文件時,就會出現這個錯誤。

模擬

# 取消測試403狀態碼的配置。隨意輸入URL進行訪問。
# curl http://127.0.0.1/aaa -H "HOST: test.qfedu.com" -I
HTTP/1.1 404 Not Found
Server: nginx/1.12.2
Date: Sun, 13 May 2018 15:11:43 GMT
Content-Type: text/html
Content-Length: 169
Connection: keep-alive
499狀態碼
499這個狀態碼並不是http協議中定義的標准狀態碼,而是Nginx自己定義的一個狀態碼。 
當客戶端主動斷開連接的時候,Nginx就會返回499的狀態碼。按照這個狀態碼的定義,只要在Nginx返回結果之前主動斷開客戶端連接,就應該會復現這個狀態碼。

測試用例

創建一個PHP腳本,並將腳本存放在Nginx 的 root 目錄中。以此腳本模擬一個很長時間的響應。

# cat sleep.php
<?php
sleep(80);
echo "ok"
?>

開啟PHP-FPM服務

# 開啟
# systemctl start php-fpm
# 查看狀態
# systemctl status php-fpm

測試Nginx配置文件

server {
   listen       80;
   server_name test.qfedu.com;
   root         /usr/share/nginx/html;
   access_log   /var/log/nginx/test.qfedu.com-acess.log;
   error_log   /var/log/nginx/test.qfedu.com-error.log;

   location ~ .*\.(gif|jpg|jpeg|png|bmp|swf|html)$ {
       expires     1d;
  }

   location / {
       # 確保 fastcgi.conf 中存在 SCRIPT_FILENAME 配置, 以下5XX案例中也要確保存在
       # fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
       include fastcgi.conf;
       # PHP-FPM 默認開啟了9000端口。若做了個性化配置,請手動調整。
       fastcgi_pass 127.0.0.1:9000;
  }
}

測試

# 不要等待程序正常結束,CTRL + C 直接退出。
# curl http://127.0.0.1/sleep.php -H "HOST: test.qfedu.com" -I
^C
# 在CURL模擬測試的同時查看 access log 
# tail -f /var/log/nginx/test.qfedu.com-acess.log
127.0.0.1 - - [13/May/2018:23:24:33 -0400] "HEAD /sleep.php HTTP/1.1" 499 0 "-" "curl/7.29.0"

5XX狀態碼

5XX 類型的狀態碼主要表示服務端錯誤。此時就不要再糾結客戶端問題了。
500狀態碼
服務器端代碼出現了異常。代碼語法錯誤、連接不上數據庫資源等等都會出現這種錯誤。

測試用例

# 將Nginx 的root 目錄中的sleep.php 隨意個更改,讓它的PHP語法出現問題。
# cat sleep.php
<?php
echo "aa"
sleep(80);
echo "ok"
?>

測試Nginx配置文件

server {
    listen       80;
    server_name  test.qfedu.com;
    root         /usr/share/nginx/html;
    access_log   /var/log/nginx/test.qfedu.com-acess.log;
    error_log    /var/log/nginx/test.qfedu.com-error.log;

    location ~ .*\.(gif|jpg|jpeg|png|bmp|swf|html)$ {
        expires      1d;
    }

    location / {
        include fastcgi.conf;
        fastcgi_pass 127.0.0.1:9000;
    }
}

模擬

# curl http://127.0.0.1/sleep.php -H "HOST: test.qfedu.com" -I
HTTP/1.1 500 Internal Server Error
Server: nginx/1.12.2
Date: Sun, 13 May 2018 15:19:14 GMT
Content-Type: text/html
Connection: keep-alive
X-Powered-By: PHP/5.4.16
502狀態碼
502 Bad Geteway。Nginx 502錯誤的原因比較多,主要是因為在代理模式下后端服務器出現問題引起的。這些錯誤一般都不是Nginx本身的問題,一定要從后端找原因。比如這里復現一種后端PHP-FPM進程掛掉的情況,就會出現502錯誤

模擬

# 先將后端的PHP-FPM進程關閉。
# systemctl stop php-fpm
# 模擬測試
# curl http://127.0.0.1/sleep.php -H "HOST: test.qfedu.com" -I
HTTP/1.1 502 Bad Gateway
Server: nginx/1.12.2
Date: Sun, 13 May 2018 15:23:28 GMT
Content-Type: text/html
Content-Length: 173
Connection: keep-alive
504狀態碼
504 Gateway Time-out。顧名思義,就是超時了。當PHP-FPM的執行時間大於Nginx的讀超時時間,此時就會出現 504狀態碼。

測試用例

NGINX

server {
   listen       80;
   server_name test.qfedu.com;
   root         /usr/share/nginx/html;
   access_log   /var/log/nginx/test.qfedu.com-acess.log;
   error_log   /var/log/nginx/test.qfedu.com-error.log;
   
   # Nginx 的讀超時設置為30s, 默認應該是60s
   fastcgi_read_timeout 30;

   location ~ .*\.(gif|jpg|jpeg|png|bmp|swf|html)$ {
       expires     1d;
  }

   location / {
       include fastcgi.conf;
       fastcgi_pass 127.0.0.1:9000;
  }
}

PHP腳本

# 恢復Nginx 的root目錄中的sleep.php腳本
# pwd
/usr/share/nginx/html
# cat sleep.php
<?php
sleep(80);
echo "ok";
?>

模擬

# 測試時,記得開啟PHP-FPM
# time curl http://127.0.0.1/sleep.php -H "HOST: test.qfedu.com" -I
HTTP/1.1 504 Gateway Time-out
Server: nginx/1.12.2
Date: Sun, 13 May 2018 15:36:20 GMT
Content-Type: text/html
Content-Length: 183
Connection: keep-alive


real 0m30.034s
user 0m0.005s
sys 0m0.009s

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM