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. Spring注解和标签的比较说明

    待完善.... xml标签 注解 说明 xml的Spring约束头 @Configuration xml约束头表明这是用于spring的的配置文件 @Configuration注解表情这是用于Spri ...

  2. python总结三

    1.线性表若采用链式存储结构的时候,要求内存中可用存储单位的地址是:连续或者不连续都可以 链式存储去找后继节点或者前驱节点是使用指针来实现的,不需要连续的内存,当然,也可以是连续的内存地址 2. 线性 ...

  3. 【Gamma】项目展示

    团队成员介绍 大娃 :后端开发人员,主要工作为后端开发,文档撰写. 大娃的个人博客 二娃 PM,主要工作为项目进度把控,例会博客撰写. 二娃的个人博客 三娃* PM,主要工作为项目进度把控,用户需求分 ...

  4. 全国自考C++程序设计

    一.单项选择题(本大题共20小题,每小题1分,共20分)在每小题列出的四个备选项中 只有一个是符合题目要求的,请将其代码填写在题后的括号内.错选.多选或未选均无 分. 1. 编写C++程序一般需经过的 ...

  5. javascript 忍者秘籍读书笔记(二)

    闭包的私有变量 function Ninja() { let feints = 0; this.getFeints = function () { return feints }; this.fein ...

  6. 词向量实践(gensim)

    词向量训练步骤: 分词并去停用词 词频过滤 训练 项目完整地址:https://github.com/cyandn/practice/tree/master/Word2Vec gensim中Word2 ...

  7. [转帖]【mount】Linux根目录空间不足

    [mount]Linux根目录空间不足 2019.04.15 21:30:47字数 1094阅读 107 一.问题背景 一台数据库服务器,突然监控告警,报根目录空间不足(no space left o ...

  8. 『Blocks 区间dp』

    Blocks Description Some of you may have played a game called 'Blocks'. There are n blocks in a row, ...

  9. 集合单列--Colletion

    集合 学习集合的目标: 会使用集合存储数据 会遍历集合,把数据取出来 掌握每种集合的特性 集合和数组的区别 数组的长度是固定的.集合的长度是可变的. 数组中存储的是同一类型的元素,可以存储基本数据类型 ...

  10. 用友U9 UFSoft.UBF.Business.Session

    Session的概念 在现在UBF中,Session的本意是work unit,即持久层的一个边界,非常轻,主要用作批量提交,并标识这次批量提交的边界,不涉及到事务等概念. 当前ISession可以通 ...