如何分析并解决因不规范HTTP请求导致的nginx响应400错误?
- 内容介绍
- 文章标签
- 相关推荐
本文共计1309个文字,预计阅读时间需要6分钟。
背景:最近分析数据时,意外发现nginx日志中一批用户HTTP POST请求均返回400错误,无200成功记录。由于仅占整体请求的不到0.5%,之前并未进行监控报警。
分析:这批用户请求均出现400错误,且无成功记录,可能存在以下原因:
1. 请求参数错误:用户在发送请求时,可能传入了错误的参数,导致服务器无法正确处理请求。
2.服务器配置问题:服务器配置可能存在问题,导致无法正确处理POST请求。
3.代码逻辑错误:后端代码在处理POST请求时,可能存在逻辑错误,导致请求无法成功处理。
建议:
1. 检查请求参数:对比正常请求和错误请求的参数,查找是否存在差异,分析可能的原因。
2.检查服务器配置:确认服务器配置是否正确,特别是与POST请求相关的配置。
3.检查后端代码:分析后端代码,查找可能存在逻辑错误的代码段。
通过以上分析,希望能找到问题所在,并尽快解决。
背景最近分析数据偶然发现nginx log中有一批用户所有的HTTP POST log上报请求均返回400,没有任何200成功记录,由于只占整体请求的不到0.5%,所以之前也一直没有触发监控报警,而且很奇怪的是只对于log上报的POST接口会存在这种特定用户全部400的情况,而对于其他接口无论POST还是GET均没有此类问题。
进一步分析log发现其实对某些地区的用户请求,这个比例甚至超过了10%,于是花时间跟进了一下,最终发现源于部分机型客户端发出的HTTP请求格式不规范导致,这里记录一下分析过程、原因以及最终解决方案。
搜寻网上资料,发现一般可能有以下几个原因会导致nginx响应400:
- request_uri 过长超过nginx配置大小
- cookie或者header过大超过nginx配置大小
- 空HOST头
- content_length和body长度不一致
这些错误其实都是发生在nginx这一层,即nginx处理时认为客户端请求格式错误,于是直接返回400,不会向upstream server转发请求,因而upstream server对这些错误请求其实完全是无感知的。
而这次根据nginx log分析,可以看到nginx其实有向upstream server转发请求--upstream_addr已经是upstream server 有效地址,所以400实际应当是upstream server返回的,而不是nginx直接返回,这说明至少nginx这一层认为请求格式是没问题的。
截取部分线上部分用户的错误日志,其大体样式如下
127.0.0.1:63646 - 24/Apr/2022:00:50:07 +0900 127.0.0.1:1080 0.000 0.000 POST /log/report?appd=abc.demo.android&appname=abcdemo&v=1.0&langes=zh-CN&phonetype=android&device_type=android&osn=Android OS 10 / API-29 (QKQ1.190825.002/V12.0.6.0.QFKCNXM)&channel=Google Play&build=Android OS 10 / API-29 (QKQ1.190825.002/V12.0.6.0.QFKCNXM)&resolution=1080x2340&ts=1650636192534 HTTP/1.1 400 50 - curl/7.52.1 - 0.000 0.000 127.0.0.1 1563 2021
日志分析可以发现大部分400请求都有一个问题:其query参数并未经过urlencode,比如可以很明显看到其参数channel=Google Play 中的空格并未转码成%20,直觉上推断这应该和400的原因有直接关系。
试错为了验证未转码query参数是否是导致400的直接原因,简单通过curl构造几个测试127.0.0.1/log/report?appd=abc.demo.android&appname=abcdemo&v=1.0&langes=zh-CN&phonetype=android&channel=Google%20Play' -d @test.json * Trying 127.0.0.1... * TCP_NODELAY set * Connected to 127.0.0.1 (127.0.0.1) port 80 (#0) > POST /log/report?appd=abc.demo.android&appname=abcdemo&v=1.0&langes=zh-CN&phonetype=android&channel=Google%20Play HTTP/1.1 > Host: 127.0.0.1 > User-Agent: curl/7.52.1 > Accept: */* > Content-Length: 1563 > Content-Type: application/x-www-form-urlencoded > Expect: 100-continue > < HTTP/1.1 100 Continue * We are completely uploaded and fine < HTTP/1.1 200 OK < Server: nginx/1.16.1 < Date: Sat, 23 Apr 2022 15:54:53 GMT < Content-Type: application/json < Content-Length: 22 < Connection: keep-alive < * Curl_127.0.0.1/log/report?appd=abc.demo.android&appname=abcdemo&v=1.0&langes=zh-CN&phonetype=android&channel=Google Play' -d @test.json * Trying 127.0.0.1... * TCP_NODELAY set * Connected to 127.0.0.1 (127.0.0.1) port 80 (#0) > POST /log/report?appd=abc.demo.android&appname=abcdemo&v=1.0&langes=zh-CN&phonetype=android&channel=Google Play HTTP/1.1 > Host: 127.0.0.1 > User-Agent: curl/7.52.1 > Accept: */* > Content-Length: 1563 > Content-Type: application/x-www-form-urlencoded > Expect: 100-continue > < HTTP/1.1 100 Continue * We are completely uploaded and fine < HTTP/1.1 400 Bad Request < Server: nginx/1.16.1 < Date: Sat, 23 Apr 2022 15:55:14 GMT < Content-Type: text/plain; charset=utf-8 < Transfer-Encoding: chunked < Connection: keep-alive < * Curl_test_log_stream; break; } include uwsgi_params; uwsgi_pass test_api_stream; }
即通过正则匹配query参数(args)中若不存在空格直接交由logsvc处理,存在空格则交由使用uwsgi协议的api主服务处理,由于此类异常请求仅占整体请求的不到0.5%,之前考虑的拆分架构依然work,只是对于少量的异常请求先通过api主服务进行兼容处理。
转载请注明出处,原文地址: www.cnblogs.com/AcAc-t/p/nginx_400_problem_for_not_encode_www.cnblogs.com/ranyonsue/p/5984001.html
www.920430.com/archives/4291504507.html
blog.csdn.net/iamlihongwei/article/details/103611655
dbaplus.cn/news-21-1129-1.html
blog.51cto.com/leejia/1434564
blog.csdn.net/kaosini/article/details/8433044
本文共计1309个文字,预计阅读时间需要6分钟。
背景:最近分析数据时,意外发现nginx日志中一批用户HTTP POST请求均返回400错误,无200成功记录。由于仅占整体请求的不到0.5%,之前并未进行监控报警。
分析:这批用户请求均出现400错误,且无成功记录,可能存在以下原因:
1. 请求参数错误:用户在发送请求时,可能传入了错误的参数,导致服务器无法正确处理请求。
2.服务器配置问题:服务器配置可能存在问题,导致无法正确处理POST请求。
3.代码逻辑错误:后端代码在处理POST请求时,可能存在逻辑错误,导致请求无法成功处理。
建议:
1. 检查请求参数:对比正常请求和错误请求的参数,查找是否存在差异,分析可能的原因。
2.检查服务器配置:确认服务器配置是否正确,特别是与POST请求相关的配置。
3.检查后端代码:分析后端代码,查找可能存在逻辑错误的代码段。
通过以上分析,希望能找到问题所在,并尽快解决。
背景最近分析数据偶然发现nginx log中有一批用户所有的HTTP POST log上报请求均返回400,没有任何200成功记录,由于只占整体请求的不到0.5%,所以之前也一直没有触发监控报警,而且很奇怪的是只对于log上报的POST接口会存在这种特定用户全部400的情况,而对于其他接口无论POST还是GET均没有此类问题。
进一步分析log发现其实对某些地区的用户请求,这个比例甚至超过了10%,于是花时间跟进了一下,最终发现源于部分机型客户端发出的HTTP请求格式不规范导致,这里记录一下分析过程、原因以及最终解决方案。
搜寻网上资料,发现一般可能有以下几个原因会导致nginx响应400:
- request_uri 过长超过nginx配置大小
- cookie或者header过大超过nginx配置大小
- 空HOST头
- content_length和body长度不一致
这些错误其实都是发生在nginx这一层,即nginx处理时认为客户端请求格式错误,于是直接返回400,不会向upstream server转发请求,因而upstream server对这些错误请求其实完全是无感知的。
而这次根据nginx log分析,可以看到nginx其实有向upstream server转发请求--upstream_addr已经是upstream server 有效地址,所以400实际应当是upstream server返回的,而不是nginx直接返回,这说明至少nginx这一层认为请求格式是没问题的。
截取部分线上部分用户的错误日志,其大体样式如下
127.0.0.1:63646 - 24/Apr/2022:00:50:07 +0900 127.0.0.1:1080 0.000 0.000 POST /log/report?appd=abc.demo.android&appname=abcdemo&v=1.0&langes=zh-CN&phonetype=android&device_type=android&osn=Android OS 10 / API-29 (QKQ1.190825.002/V12.0.6.0.QFKCNXM)&channel=Google Play&build=Android OS 10 / API-29 (QKQ1.190825.002/V12.0.6.0.QFKCNXM)&resolution=1080x2340&ts=1650636192534 HTTP/1.1 400 50 - curl/7.52.1 - 0.000 0.000 127.0.0.1 1563 2021
日志分析可以发现大部分400请求都有一个问题:其query参数并未经过urlencode,比如可以很明显看到其参数channel=Google Play 中的空格并未转码成%20,直觉上推断这应该和400的原因有直接关系。
试错为了验证未转码query参数是否是导致400的直接原因,简单通过curl构造几个测试127.0.0.1/log/report?appd=abc.demo.android&appname=abcdemo&v=1.0&langes=zh-CN&phonetype=android&channel=Google%20Play' -d @test.json * Trying 127.0.0.1... * TCP_NODELAY set * Connected to 127.0.0.1 (127.0.0.1) port 80 (#0) > POST /log/report?appd=abc.demo.android&appname=abcdemo&v=1.0&langes=zh-CN&phonetype=android&channel=Google%20Play HTTP/1.1 > Host: 127.0.0.1 > User-Agent: curl/7.52.1 > Accept: */* > Content-Length: 1563 > Content-Type: application/x-www-form-urlencoded > Expect: 100-continue > < HTTP/1.1 100 Continue * We are completely uploaded and fine < HTTP/1.1 200 OK < Server: nginx/1.16.1 < Date: Sat, 23 Apr 2022 15:54:53 GMT < Content-Type: application/json < Content-Length: 22 < Connection: keep-alive < * Curl_127.0.0.1/log/report?appd=abc.demo.android&appname=abcdemo&v=1.0&langes=zh-CN&phonetype=android&channel=Google Play' -d @test.json * Trying 127.0.0.1... * TCP_NODELAY set * Connected to 127.0.0.1 (127.0.0.1) port 80 (#0) > POST /log/report?appd=abc.demo.android&appname=abcdemo&v=1.0&langes=zh-CN&phonetype=android&channel=Google Play HTTP/1.1 > Host: 127.0.0.1 > User-Agent: curl/7.52.1 > Accept: */* > Content-Length: 1563 > Content-Type: application/x-www-form-urlencoded > Expect: 100-continue > < HTTP/1.1 100 Continue * We are completely uploaded and fine < HTTP/1.1 400 Bad Request < Server: nginx/1.16.1 < Date: Sat, 23 Apr 2022 15:55:14 GMT < Content-Type: text/plain; charset=utf-8 < Transfer-Encoding: chunked < Connection: keep-alive < * Curl_test_log_stream; break; } include uwsgi_params; uwsgi_pass test_api_stream; }
即通过正则匹配query参数(args)中若不存在空格直接交由logsvc处理,存在空格则交由使用uwsgi协议的api主服务处理,由于此类异常请求仅占整体请求的不到0.5%,之前考虑的拆分架构依然work,只是对于少量的异常请求先通过api主服务进行兼容处理。
转载请注明出处,原文地址: www.cnblogs.com/AcAc-t/p/nginx_400_problem_for_not_encode_www.cnblogs.com/ranyonsue/p/5984001.html
www.920430.com/archives/4291504507.html
blog.csdn.net/iamlihongwei/article/details/103611655
dbaplus.cn/news-21-1129-1.html
blog.51cto.com/leejia/1434564
blog.csdn.net/kaosini/article/details/8433044

