nginx 400状态码排查
最近,发现主站nginx的log中有很多400的错误,每天有几千万条,故决定对产生400错误的原因进行排查。分析nginx log,发现这种无效的400请求,总是在一个正常访问之后产生,一般出现一个或者几个。log格式如下:
下面对这种情况进行分析:
一,nginx 400状态码含义
A client MUST include a Host header field in all HTTP/1.1 request messages . If the requested URI does not include an Internet host name for the service being requested, then the Host header field MUST be given with an empty value. An HTTP/1.1 proxy MUST ensure that any request message it forwards does contain an appropriate Host header field that identifies the service being requested by the proxy. All Internet-based HTTP/1.1 servers MUST respond with a 400 (Bad Request) status code to any HTTP/1.1 request message which lacks a Host header field.
上面是http1.1的rfc关于host部分的解释,从上面我们了解到如果一个http1.1的请求没有host域,那么server应该给client段发送400的状态码,表明这个请求server不能处理。而对于nginx server来说,也遵循这样的方式,说明client发送了一个无效的请求,nginx server无法处理,故返回400的状态码。
参见:http://www.w3.org/Protocols/rfc2616/rfc2616.html
二,重现400请求
1,我使用pc端的chrome和ucweb浏览器,对网站进行访问,发现nginx log中的确会产生400的log,在nginx server端通过netstat看了一下client和server段建立的tcp连接数,每一个请求都是在3个以上。而是用ie和firefox浏览器对网站进行访问,发现不能重现400的log,在nginx server端通过netstat看了一下client和server段建立的tcp连接数,每一个请求都是只有1个。
2,使用telnet登录nginx的80端口
[@zw-81-90 ~]# telnet 10.13.82.96 80
Trying 10.13.82.96...
Connected to 10.13.82.96 (10.13.82.96).
Escape character is '^]'.
Connection closed by foreign host.
使用telnet连接后,直接断开连接即可
三,问题分析
第一种情况:
通过分析nginx的log,发现400请求中chrome和ucweb的ua比较多,通过查看相关的文章发现,这种请求和浏览器的自身策略有关系。
通常我们访问一个网站时,第一个获取的是一个html主文件,而里面链接了网页所需要的css、js、图片等其他媒体资源文件,而一般资源文件和主html文件是在一个域下的,而像chrome这种浏览器就会使用pre-connection,即在获取html之前就与nginx server建立多个的tcp连接,而不是等到获取到html文件之后再去连接服务器获取这个域名下的其他文件,因为连接服务器是需要消耗一些时间的,所以这项技术可以很大程度上加快网页的呈现速度。当然,浏览器同一时间针对同一域名下的请求也是有一定数量限制。
如果网页html链接的资源比较少,或者客户端有缓存,不需要连接下载,那么Chrome浏览器发出的5-6个连接很可能只有1个是需要的,其他的都得关闭掉,这样就产生了一个问题:连接了服务器,而没有发送任何请求,当然也没有host头了。对于这种情况,nginx是当做400错误来处理的,但由于连接已经关闭,错误信息不会发送到客户端,这就产生了日志文件中记录的400错误。
第二种情况:
使用telnet与nginx server建立个tcp连接,但是没有发送任何数据,当然也没有host头,之后四次挥手断开了连接。这种情况,nginx也是当作400的错误来处理的。使用tcpdump抓包,wireshark分析过程的截图如下:
当然,我们发现使用nagios的check_tcp插件对nginx server端口做检测或者使用keepalived的tcp_check功能对后端nginx端口的存活做检测,这两种情况都会在nginx log中产生400的请求。原因也很简单,就是第二种情况的理由,一般tcp check的方式,就是建立tcp连接,然后再reset或者四次挥手断开连接。
四,解决办法
nginx官方提供了一种方法,使用虚拟主机来匹配那些在nginx上没有匹配到host的请求。这样那些空host的请求,会被这个虚拟主机所匹配。如果不加这个虚拟主机的话,如果nginx上的虚拟主机没有对应client请求的host,nginx默认是用nginx.conf中第一个虚拟主机的处理,故400的请求就会出现在第一个虚拟主机的log中。虚拟主机配置如下:
server {
listen 80 default_server;
server_name _;
return 404;
access_log off;
}
总之,目前分析来看这类400的无效请求属于正常现象,可以用虚拟主机来消除400的请求。
转载于:https://blog.51cto.com/leejia/1434564
nginx 400状态码排查相关推荐
- 请求头有问题导致Nginx返回400状态码
背景 上个星期有人找我看了Nginx的问题,场景是这样的,用户访问一个网址,这个网址有一个按钮,点击这个按钮后会跳转到新的页面,但这个跳转,有时候可以,有时候不可以--不可以的时候页面显示400状态码 ...
- nginx返回400状态码
分析: 1.后端地址正常返回200: 2.确认是url加上参数后,nginx返回400,并且nginx除了400状态码的访问日志,没有输出其他异常日志: nginx地址: https://test.c ...
- nginx 返回状态码详解
nginx 返回状态码详解 200 (成功) 服务器已成功处理了请求. 通常,这表示服务器提供了请求的网页. 201 (已创建) 请求成功并且服务器创建了新的资源. 202 (已接受) 服务器已接受请 ...
- put请求400状态码
put请求400状态码 后台检查数据类型是否匹配与前台传过来的是否对应 private String phone; private String verifyCode; 查看接收参数是使用@Reque ...
- get请求报错400状态码
get请求报错400状态码 请求参数带 {} 在tomcat 7版本中没有问题,可以正常返回请求 在tomcat8.5.35 版本中 请求报错400 原因分析: Tomcat的新版本中增加了一个新 ...
- axios post 400 状态码
1.400状态码 400的主要有两种形式: (1).bad request意思是"错误的请求": (2).invalid hostname意思是"不存在的域名" ...
- axios发送post请求返回400状态码
axios发送post请求返回400状态码 今天在用 axios 发送一个跨域的post请求时,遇到了一个坑:Uncaught (in promise) Error: Request failed w ...
- scrapy 爬虫报415状态码和400状态码
今天用Scrapy框架时出现了一些小问题,折腾了半天,记录一下. 返回415状态码:请求包未加header 请求包 这是一个POST请求并需要提交表单数据,所以我用了scrapy.FormReques ...
- get请求400错误 vue_解决axios发送post请求返回400状态码的问题
今天在用 发送一个跨域的post请求时,遇到了一个坑:uncaught (in promise) error: request failed with status code 400. 前台代码如下: ...
最新文章
- GO语言有哪些优势?怎样入门?
- 数据中心网络架构 — 云数据中心网络 — 新型叶脊二层网络架构
- leetcode算法题--排序链表★
- boost::math模块非有限环回的基本测试
- Cacti监控一台Webserver上多个Tomcatport的实现
- 多线程进一步的理解------------线程的创建
- php 标点符号反转,PHP删除标点符号(无破折号)
- php 匹配双字节字符串,收集一些常用的正则表达式(匹配中文字符、匹配双字节字符、匹配HTML标记、匹配空行 and so on~~~)...
- HTML文字横向滚动
- ElasticSearch 5.5.3 Docker化部署
- day6-day9代码片段
- oracle 错误01017,ORA-01017:用户名密码出错 故障实例
- 3D优化之ShadowGun系列二:浓烟,使用面片模拟粒子效果
- 163邮箱提示: 535 Error: authentication failed
- 什么是hadoop?
- 汇编语言上机的4个步骤
- css设置格子背景,跟本子一样
- 基于Java毕业设计房屋租赁平台源码+系统+mysql+lw文档+部署软件
- 基于FPGA的FFT
- Acer 4750 安装黑苹果_黑苹果安装体验初始阶段几个小技巧
热门文章
- 数据库 版本号是 661,打不开。此server支持 655 和更早的版本号。不支持降级路径...
- C++开源代码项目汇总
- MyBatis之级联——一对一关系
- SpringMVC_实现简单的增删改查
- Oh-My-Zsh及主题、插件安装与配置
- Spring 基于Java配置
- Java 8 Lambda 表达式详解
- 【Laravel学习篇 · 一】Windows下起步就遇麻烦
- Linux umount 报 device is busy 的处理方法
- Windows7下最新Android开发环境搭建(JDK1.7 + Eclipse Indigo(3.7) + SDK-r12 + ADT-12)