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

HTTP状态码面试必知的更多相关文章

  1. Java面试必知必会:基础

    面试考察的知识点多而杂,要完全掌握需要花费大量的时间和精力.但是面试中经常被问到的知识点却没有多少,你完全可以用 20% 的时间去掌握 80% 常问的知识点. 一.基础 包括: 杂七杂八 面向对象 数 ...

  2. Java面试必知必会(扩展)——Java基础

    float f=3.4;是否正确? 不正确 3.4是双精度,将双精度赋值给浮点型属于向下转型,会造成精度损失: 因此需要强制类型转换: 方式一:float f=(float)3.4 方式二:float ...

  3. 转载 java基础题(面试必知)

    1.面向对象的特征有哪些方面 1.抽象:抽象就是忽略一个主题中与当前目标无关的那些方面,以便更充分地注意与当前目标有关的方面.抽象并不打算了解全部问题,而只是选择其中的一部分,暂时不用部分细节.抽象包 ...

  4. php面试必知必会常见问题

    1 说出常用的10个数组方法 我觉得数组比较最能体现PHP基础语法的一个数据结构了,下面给大家列一下常用的10个关于操作数组的函数 in_array(判断数组中是否有某个元素) implode(将数组 ...

  5. 面试必知:String、StringBuilder、StringBuffer的区别

    你知道String.StringBuilder.Stringbuffer的区别吗?当你创建字符串的时候,有考虑过该使用哪个吗? 别急,这篇文章带你解决这些问题. 可变性 首先,String是字符串,我 ...

  6. (转)C系程序员面试必知必会之大端小端

      C程序员经常被问及的一道面试题是:什么是大端/小端,怎么样判断是大端/小端?大端小端问题对于嵌入式程序员绝对不会陌生(否则,别告诉我你是搞嵌入式的),它与CPU体系结构有关.比如常见的X86处理器 ...

  7. java面试必知必会——排序

    二.排序 时间复杂度分析 排序算法 平均时间复杂度 最好 最坏 空间复杂度 稳定性 冒泡 O(n²) O(n) O(n²) O(1) 稳定 选择 O(n²) O(n²) O(n²) O(1) 不稳定 ...

  8. 面试必知道的APP测试adb命令

    查看当前连接设备: adb devices 如果发现多个设备: adb -s 设备号 其他指令 查看日志: adb logcat 安装apk文件: adb install xxx.apk 此安装方式, ...

  9. 15分钟带你了解前端工程师必知的javascript设计模式(附详细思维导图和源码)

    15分钟带你了解前端工程师必知的javascript设计模式(附详细思维导图和源码) 前言 设计模式是一个程序员进阶高级的必备技巧,也是评判一个工程师工作经验和能力的试金石.设计模式是程序员多年工作经 ...

随机推荐

  1. Android Studio 之 GridView

    1. 数据源 ArrayList Cursor 2. 适配器 Adapter ArrayAdapter SmipleAdapter SmipleCursorAdapter BaseAdapter

  2. Linux+Nginx+Supervisor部署ASP.NET Core实操手册

    一.课程介绍 在上一节课程<ASP.NET Core托管和部署Linux实操演练手册>中我们学过net core的部署方式多样性和灵活性.我们通过远程工具输入dotnet 程序集名称.dl ...

  3. 非mvn项目转为mvn项目并构建mvn私服

    非mvn项目转为mvn项目并构建mvn私服 一.背景 公司里的系统是老系统,没有使用mvn,但是现在准备使用持续集成(CI),就要用到mvn,所以现在需要将老项目转为mvn项目,并且非mvn项目也是不 ...

  4. logstash设置开机自启动

    本篇文件前提是在centos7.6上使用rpm包安装的logstash,添加systemd方式启动. #默认为rpm包安装,进行执行目录 cd /usr/share/logstash/bin/ #系统 ...

  5. 30分钟用 Laravel 实现一个博客

    介绍 Laravel 是一款 MVC架构. 目前最流行的 PHP框架. Laravel的优点在于: 丰富的composer类库支持, 优雅的代码, 未来的主流框架(目前市场占有率最高的框架) Lara ...

  6. LeetCode dp专题

    1. 动态规划的适用场景 动态规划常常适用于有重叠子问题和最优子结构性质的问题,动态规划方法所耗时间往往远少于朴素解法. 2. 动态规划的基本思想 动态规划背后的基本思想非常简单.大致上,若要解一个给 ...

  7. 基于网络拓扑图通过RCMS对网络进行配置

    目录 基于网络拓扑图通过RCMS对网络进行配置 一些基本命令 对网络拓扑图1的简单配置 二层交换机S3 三层交换机 S2 实验结果 对网络拓扑图2的简单配置 NAT.ACL配置公网IP 基于网络拓扑图 ...

  8. apache添加ssl协议实现用户认证

    目标 1对服务器的访问由http改为https, 2仅有证书的客户端可以访问服务器, 3.通过服务器端的配置,可以停用某个客户端的证书. 一 Apache服务器相关配置: 在../apache/con ...

  9. B树和B+树的增/删结点(转)

    add by zhj: 算法其实不复杂,尤其是增加结点的算法,逻辑很简单,但有时自己想不到. 增加结点算法:首先,对于B树,没有重复结点,所以新插入的数据一定会落在叶结点上,或者说落在叶结点的所有父结 ...

  10. 可落地的DDD(3)-如何利用DDD进行微服务的划分

    摘要 前面两篇介绍了DDD的目标管理.DDD的工程结构调整.这篇讨论微服务的划分.微服务是目前后端比较流行的架构体系了,那么如何做好一个微服务的划分?一个微服务的粒度应该是多大呢?这篇主要介绍如何结合 ...