那一天,人们终于回想起了被BUG支配的恐惧
Toggle navigation
Home
AboutMe
Links
Archives
Tags
Nginx状态码
2016-02-23 11:34:31
5339
0
1
weibo-007
#目录 [TOC] #前言 本文目的旨在对http状态码含义做一个基本解释,不会太深入讨论每个状态码,由于每个http状态码的出现可能对应多种情况,本文可能也考虑不周全。总之,看完本文,能够对http状态码有一个更加直观的认知。本文的思路是一个状态码加一个重现例子的方式呈现。 #坏境搭建 本文的测试需要的linux+nginx+PHP环境,可以不需要MySQL。搭建环境的资料如下: [lnmp.zip](http://leanote.com/api/file/getAttach?fileId=56c686e6ab64413b370005fc) #http状态码分类 1. 消息类(1字头) 2. 成功类(2字头) 3. 重定向类(3字头) 4. 请求错误类(4字头) 5. 服务器错误类(5、6字头) 中途可能会穿插nginx自定义的http状态码,nginx状态码本身不属于http状态码了,只是在nginx内部自己定义的一套状态码,但是在nginx日志中,却经常出现 #请求错误类(客户端错误) ##400 400的英文含义`400 Request Header Or Cookie Too Large`,顾名思义,头信息或者Cookie信息太多了 复现这个状态码只需要添加够长的头信息或者Cookie信息即可,构造一个curl请求: ``` curl --header "Cookie:sidisisidisidisisidisidisisidisidisisidisidisisidisidisisidisidisidisisidisisidisidisisidisidisisidisidisisidisidisisidisidisisidisidissidisisidisidisisidisidisisidisidisisidisidisisidisidisisidisidissidisisidisidisisidisidisisidisidisisidisidisisidisidisisidisidissidisisidisidisisidisidisisidisidisisidisidisisidisidisisidisidissidisisidisidisisidisidisisidisidisisidisidisisidisidisisi....." http://localhost:80 ``` 执行这个curl命令可以看到提示: <img src="http://leanote.com/api/file/getImage?fileId=56c696edab64413c8b000739"/ width="500"> ##401 401的含义是`401 Authorization Required`,顾名思义,就是需要权限认证,但是客户端又没有通过认证。复现这个状态码必须对nginx调整成认证模式。现在,将nginx调成认证模式,nginx的server模块配置如下 ``` location / { auth_basic "secret";#认证模式 auth_basic_user_file /usr/local/nginx/passwd.db;#密码文件 root html2; index index.html index.htm; } ``` 接下来生成密码文件 ``` sh-3.2# htpasswd -c /usr/local/nginx/passwd.db yongxiongzhong New password: Re-type new password: Adding password for user yongxiongzhong ``` 更改权限 ``` chmod 400 /usr/local/nginx/passwd.db ``` 平滑重启nginx之后,再次访问网页可以看到认证界面 <img src="http://leanote.com/api/file/getImage?fileId=56c74371ab64413b37000dae" width="500"> 点击取消按钮,则可以看到以下这个页面 <img src="http://leanote.com/api/file/getImage?fileId=56c743b6ab64413c8b000e2a" width="500" /> ##403 403的出现,大部分是没有对文件进行授权。`403 Forbidden`顾名思义就是禁止访问,重现这个状态码只需要修改访问文件的权限,比如给nginx网站根目录中的index文件减少权限 ``` chmod 0 /usr/local/nginx/html/index.html ``` 当我们再次访问这个文件是,就会出现403错误 <img src="http://leanote.com/api/file/getImage?fileId=56c74731ab64413c8b000e39" width="500"/> ##404 404算是我们经常碰到的状态码,`404 Not Found`当我们访问一个不存在的文件时,就会出现这个错误 在URL地址栏上随便访问一个不存在的文件,就会出现 <img src="http://leanote.com/api/file/getImage?fileId=56c748b5ab64413c8b000e40" width="500"/> 在实际生产环境中,这样的404页面并不好看,所以可以通过在server中配置自定义404页面: ``` error_page 404 /my_404.html; ``` 其中在网站根目录新建my_404.html然后写入自定义内容。平滑重启nginx之后,再次访问一些不存在的页面时会提示如下: <img src="http://leanote.com/api/file/getImage?fileId=56ca69f9ab64413b37001d8a" width="500" /> ##405 405状态码并不算常见,它表示`405 Not Allowed`。http请求可以支持GET,POST,PUT,DELETE方式。默认情况下,如果你对一个html静态文件进行post请求的话,就会出现405错误 <img src="http://leanote.com/api/file/getImage?fileId=56c74c92ab64413b37000dd9" width="500" /> ##413 413也是比较容易出现的一种状态码,413的出现常常伴随着`413 Request Entity Too Large`表示请求实体过大导致。用户上传的Content-Length大于nginx设定的最大值时。比如上传一张很大的图片,就会出现413错误码 <img src="http://leanote.com/api/file/getImage?fileId=56c89aa1ab64413b3700152d" width="500"/> 这个是由参数client_max_body_size控制的,默认是1M。有点小,所以一般线上环境调成以下配置即可消除上面的问题 ``` client_max_body_size 8m; ``` ##414 一般出现这个错误的时候,也伴随着一段英文提示`414 Request-URI Too Large`,也就是说我们请求的url太长了,如果我们把一个很长的url放在浏览器地址栏上,浏览器的保护措施,并不会出现414报错。所以要重现这个414错误码,只能通过curl命令。申请如下一个很长的url,篇幅问题,最后用...代替: ``` curl http://localhost:8080/?key=abcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefg.... ``` 运行这个curl命令,就可以看到414错误 ![图片标题](http://leanote.com/api/file/getImage?fileId=56c89ca0ab64413b37001539) 在nginx中,以下两个参数共同决定这个问题 ``` client_header_buffer_size large_client_header_buffers ``` ##499(nginx status) 499这个状态码并不是http协议中定义的status code,而是nginx自己定义的一个状态码。 当客户端主动断开连接的时候,nginx就会返回499的状态码。按照这个状态码的定义,复现这个状态码很容易,只要在nginx返回结果之前断开客户端连接。所以,下一个data.php文件 ``` <?php sleep(10);//睡觉10秒钟 ``` 然后在浏览器访问http://localhost:8000/data.php,注意,在10秒之内关闭浏览器以断开客户端连接。然后在查看nginx访问日志就能看到499错误 <img src="http://leanote.com/api/file/getImage?fileId=56c9b087ab64413b37001a89" width="500" /> 值得一提的是,在线上环境中,如果并发量大的话,nginx未能及时处理完请求,导致客户端“不干了”,这是会大量爆发499错误。这种情况可以用ab工具测试,ab工具中,-n为请求次数,-c为并发量: ``` ab -n 100 -c 100 http://127.0.0.1:8000/data.php ``` 再观察我们的nginx访问日志,会发现大量的499 <img src="http://leanote.com/api/file/getImage?fileId=56c9b174ab64413c8b001a58" width="500" /> #服务端错误 ##500 http状态码500表示内部服务器错误,这个错误一般是php代码出现error导致,如果你没有关闭php错误提示,当写一个错误的php脚本时,网页上会出现以下错误提示 <img src="http://leanote.com/api/file/getImage?fileId=56c9a0f1ab64413c8b0019f2" width="500"/> 但是一般情况下这些错误我们并不希望就这样暴露给客户端,因为将这些错误信息暴露是一件很危险的事情,别人可以通过你的错误猜测系统漏洞。所以在线上一般是关闭错误显示,关闭方式为:编辑php-fpm.conf关闭错误信息,保存php-fpm以下设置项 ``` php_flag[display_errors] = off ``` 平滑重启php-fpm进程之后,再次访问一个包含错误语法的php错误的时候,会报500错误。 <img src="http://leanote.com/api/file/getImage?fileId=56c9a272ab64413c8b0019fe" width="500" /> ##502 当出现502这个错误的时候,也伴随着一句英文`502 bad geteway`,很醒目的一段问题,出现这个错误的时候,因为这是服务端错误,可以定位`挂掉了`。Nginx 502错误的原因比较多,是因为在代理模式下后端服务器出现问题引起的。这些错误一般都不是nginx本身的问题,一定要从后端找原因。比如这里复现一种后端php-fpm进程挂掉的情况,关闭php-fpm ``` kill -9 `ps aux | grep php-fpm | grep -v grep | awk -F ' ' '{print $2}'` ``` 再次访问我们的php文件时候,然后就可以看到网站挂掉的情况 <img src="http://leanote.com/api/file/getImage?fileId=56c9a4a0ab64413c8b001a0b" width="500" /> ##503 注意,出现503的时候服务没挂,出现503的时候伴随着`503 Service Temporarily Unavailable`,这句话告诉我们服务是暂时性不可用,nginx官方文档上有说明这一点, >Sets the shared memory zone and the maximum allowed number of connections for a given key value. When this limit is exceeded, the server will return the 503 (Service Temporarily Unavailable) error in reply to a request. 简单的说,就是在控制请求频率和并发数,详细配置可以参考nginx官方文档:http://nginx.org/en/docs/http/ngx_http_limit_conn_module.html#limit_conn 这里只复现一种可能的情况,将nginx配置如下(两个核心配置,省去了很多): ``` http { limit_conn_zone $binary_remote_addr zone=addr:10m; server { limit_conn addr 1;#并发数为1,好测试 ``` 注意测试的时候,不是所有的连接都算进去,也就是并发数为1,并不代表只能并发1,nginx说明: >Not all connections are counted. A connection is counted only if it has a request processed by the server and the whole request header has already been read. 然后采用ab测试工具,运行如下命令 ``` ab -n 2 -c 2 http://127.0.0.1:8000/data.php ``` 查看nginx访问日志,可以看到503报错信息 <img src="http://leanote.com/api/file/getImage?fileId=56cd6045ab64413c8b003002" width="500"/> ##504 当出现504的时候也伴随着一段英文,`504 Gateway Time-out`,顾名思义,就是超时了,复现这个错误码也很简单。让你的php程序模拟耗时请求,比如把php脚本里添加以下内容 ``` <?php sleep(70);//模拟耗时,睡70秒 echo "睡醒了"; ``` 然后通过域名访问这个脚本文件,就会出现超时的界面 <img src="http://leanote.com/api/file/getImage?fileId=56c9c05eab64413b37001afc" width="500"/> #重定向和缓存 ##301和302 之所以将这两个状态码放到一起,因为他们都是重定向,其中,`301永久重定向`,`302暂时重定向`。不管是暂时还是临时,对用户而言,这两者没什么区别,都是在访问A网站的时候跳转到了B网站,并看到浏览器上的地址栏变成了B网站的地址。有区别的是搜索引擎,搜索引擎是要建立索引规则和权重的,如果网站A被设定为永久重定向到B,那搜索引擎可以确定A的地址永久改变了,就会把B当做唯一有效的目标地址,这是搜索引擎会把老地址的PageRank等信息带到新地址,同时在搜索引擎索引库中彻底废弃掉原先的老地址。所以,所以只要网站不是临时性迁移,都会做301重定向。 在nginx的rewrite语法中有两个关键字 `permanent——永久重定向 redirect——临时重定向` 如果我们想要将.asp文件永久重定向到index页面 ``` location ~ \.asp$ { rewrite ^(.*)$ /index.html permanent; } ``` <img src="http://leanote.com/api/file/getImage?fileId=56c9bd30ab64413b37001aee" width="500"/> 如果只想临时重定向到index页面。 ``` location ~ \.asp$ { rewrite ^(.*)$ /index.html redirect; } ``` 再次访问页面是可以看到302冲重定向了,同样,浏览器地址栏上的地址变成了重定向后的地址 <img src="http://leanote.com/api/file/getImage?fileId=56c9bdb0ab64413b37001af0" width="500"/> ##304 `304 Not Modified`,默认情况下,nginx会对静态文件进行缓存。为了节省网络宽带,nginx和浏览器会产生如下交互 ``` 1. 浏览器客户端想请求一个文档,如果浏览器本地已经有缓存了,发送If-Modified-Since给Web服务器 2. 服务器将文件最后修改时间将服务器的文档修改时间Last-Modified和浏览器发送过来的If-Modified-Since比较,如果两者一致,返回304给浏览器,告诉浏览器用本地缓存就好了,如果两者不一致,返回200给浏览器,告诉浏览器使用最新的文档 ``` 在默认情况下,在浏览器中输入`http://localhost:8000/test.css`请求css文件**两次**就会出现304 <img src="http://leanote.com/api/file/getImage?fileId=56cad79dab64413b37002183" width="500"/> 如果在服务器端编辑`test.css`文件,由于这个时间文件最后修改时间发生了变更,这时服务器不会返回304状态码了。这时返回200状态码,两个的时间不一样了,浏览器采用最新的。 <img src="http://leanote.com/api/file/getImage?fileId=56cadf78ab64413b370021b4" width="500" /> 有关于各种缓存策略这里不做讨论。
Pre:
数据库设计范式
Next:
MySQL如何选择float, double, decimal
0
likes
5339
Weibo
Wechat
Tencent Weibo
QQ Zone
RenRen
Submit
Sign in
to leave a comment.
No Leanote account?
Sign up now.
1
comments
More...
Table of content
No Leanote account? Sign up now.