最近,发现主站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状态码排查相关推荐

  1. 请求头有问题导致Nginx返回400状态码

    背景 上个星期有人找我看了Nginx的问题,场景是这样的,用户访问一个网址,这个网址有一个按钮,点击这个按钮后会跳转到新的页面,但这个跳转,有时候可以,有时候不可以--不可以的时候页面显示400状态码 ...

  2. nginx返回400状态码

    分析: 1.后端地址正常返回200: 2.确认是url加上参数后,nginx返回400,并且nginx除了400状态码的访问日志,没有输出其他异常日志: nginx地址: https://test.c ...

  3. nginx 返回状态码详解

    nginx 返回状态码详解 200 (成功) 服务器已成功处理了请求. 通常,这表示服务器提供了请求的网页. 201 (已创建) 请求成功并且服务器创建了新的资源. 202 (已接受) 服务器已接受请 ...

  4. put请求400状态码

    put请求400状态码 后台检查数据类型是否匹配与前台传过来的是否对应 private String phone; private String verifyCode; 查看接收参数是使用@Reque ...

  5. get请求报错400状态码

    get请求报错400状态码  请求参数带  {} 在tomcat 7版本中没有问题,可以正常返回请求 在tomcat8.5.35 版本中 请求报错400 原因分析: Tomcat的新版本中增加了一个新 ...

  6. axios post 400 状态码

    1.400状态码 400的主要有两种形式: (1).bad request意思是"错误的请求": (2).invalid hostname意思是"不存在的域名" ...

  7. axios发送post请求返回400状态码

    axios发送post请求返回400状态码 今天在用 axios 发送一个跨域的post请求时,遇到了一个坑:Uncaught (in promise) Error: Request failed w ...

  8. scrapy 爬虫报415状态码和400状态码

    今天用Scrapy框架时出现了一些小问题,折腾了半天,记录一下. 返回415状态码:请求包未加header 请求包 这是一个POST请求并需要提交表单数据,所以我用了scrapy.FormReques ...

  9. get请求400错误 vue_解决axios发送post请求返回400状态码的问题

    今天在用 发送一个跨域的post请求时,遇到了一个坑:uncaught (in promise) error: request failed with status code 400. 前台代码如下: ...

最新文章

  1. GO语言有哪些优势?怎样入门?
  2. 数据中心网络架构 — 云数据中心网络 — 新型叶脊二层网络架构
  3. leetcode算法题--排序链表★
  4. boost::math模块非有限环回的基本测试
  5. Cacti监控一台Webserver上多个Tomcatport的实现
  6. 多线程进一步的理解------------线程的创建
  7. php 标点符号反转,PHP删除标点符号(无破折号)
  8. php 匹配双字节字符串,收集一些常用的正则表达式(匹配中文字符、匹配双字节字符、匹配HTML标记、匹配空行 and so on~~~)...
  9. HTML文字横向滚动
  10. ElasticSearch 5.5.3 Docker化部署
  11. day6-day9代码片段
  12. oracle 错误01017,ORA-01017:用户名密码出错 故障实例
  13. 3D优化之ShadowGun系列二:浓烟,使用面片模拟粒子效果
  14. 163邮箱提示: 535 Error: authentication failed
  15. 什么是hadoop?
  16. 汇编语言上机的4个步骤
  17. css设置格子背景,跟本子一样
  18. 基于Java毕业设计房屋租赁平台源码+系统+mysql+lw文档+部署软件
  19. 基于FPGA的FFT
  20. Acer 4750 安装黑苹果_黑苹果安装体验初始阶段几个小技巧

热门文章

  1. 数据库 版本号是 661,打不开。此server支持 655 和更早的版本号。不支持降级路径...
  2. C++开源代码项目汇总
  3. MyBatis之级联——一对一关系
  4. SpringMVC_实现简单的增删改查
  5. Oh-My-Zsh及主题、插件安装与配置
  6. Spring 基于Java配置
  7. Java 8 Lambda 表达式详解
  8. 【Laravel学习篇 · 一】Windows下起步就遇麻烦
  9. Linux umount 报 device is busy 的处理方法
  10. Windows7下最新Android开发环境搭建(JDK1.7 + Eclipse Indigo(3.7) + SDK-r12 + ADT-12)