美文网首页
HTTP状态码499,502,503,504的原理及复现

HTTP状态码499,502,503,504的原理及复现

作者: 后厂村村长 | 来源:发表于2023-03-17 15:17 被阅读0次

    502,504在超时场景下很容易被混淆,区分起来有一定难度;
    499 产生的原因往往也会和 504 会有内在关联。

    注:因为是连续测试,所以修改nginx或php-fpm配置后,记得重启。

    基本环境(LNMP):

    nginx 配置
    fastcgi_connect_timeout 5; # nginx连接fastcgi的超时时间
    fastcgi_send_timeout 10; #nginx往fastcgi发送参数的超时时间
    fastcgi_read_timeout 10; #nginx从fastcig获取数据的超时时间
    php-fpm 配置
    request_terminate_timeout = 30 ; 一次请求的最长执行时间
    PHP脚本:
    nginx的webroot创建codetest.php文件,通过访问 localhost/codetest.php 复现http响应code;

    499 复现

    php-fpm.conf:
    request_terminate_timeout=30
    nginx:
    fastcgi_read_timeout 5;
    代码:
    sleep(15);
    echo 'hello world';

    499报错信息: Client Closed Request;即 客户端主动断开连接。

    指一次http请求在客户端指定的时间内没有返回响应,此时,客户端会主动断开连接,此时表象为客户端无响应返回;
    此状态码在浏览器请求时几乎不可见,因为浏览器默认超时时间很长
    多见于业务架构中的服务模块之间的调用。

    复现途径:

    在linux终端使用curl命令请求,-m 表示超时时间,单位秒
    curl -i -m 3 http://127.0.0.1/codetest.php
    返回:
    Operation timed out after 3004 milliseconds with 0 bytes received
    此时,nginx的 access_log 会出现如下信息:
    "HEAD /codetest.php HTTP/1.1" 499

    502 复现

    502,Bad Gateway,网关错误,它往往表示网关从上游服务器中接收到的响应是无效的。

    先来了解一下网关是什么含义

    从宏观定义上来说只要是连接两个不同网络设备的都可以叫网关,具体到Http请求这里,网关就是指是转发其他服务器通信数据的服务器,于本文而言,Nginx 就是网关。

    502并不是指网关本身出了问题,而是从上游接收响应出了问题,比如由于上游服务自身超时导致不能产生响应数据,或者上游不按照协议约定来返回数据导致网关不能正常解析。

    复现路径-1

    关闭php-fpm进程,返回502。
    这个比较容易理解,参照上面的定义,因为php-fpm进程关闭,nginx连接不上php-fpm,即nginx不能收从上层接收到响应数据。

    nginx 错误日志类似如下内容:
    connect() to unix:xxxx/php-cgi.sock failed (2: No such file or directory) while connecting to upstream

    复现路径-2

    启动php-fpm进程,修改php-fpm.conf的 request_terminate_timeout 和php代码的 sleep 时间来复现。
    php代码:
    sleep(15); echo 'hello world';
    php-fpm.conf
    request_terminate_timeout=5
    nginx
    fastcgi_read_timeout 10;
    php-fpm.conf设置的最大执行时间是5s,但是php脚本需要的执行时间大于15s,所以php-fpm进程执行5s时就回退出,此时php脚本没有正常执行完成,所以返回给网关Nginx的数据异常,于是导致502。

    php-fpm错误日志如下:
    script '/webroot/codetest.php' (request: "GET /codetest.php") execution timed out (5.161544 sec), terminating
    nginx错误日志
    recv() failed (104: Connection reset by peer) while reading response header from upstream

    503 复现

    如果你搜索 503,大部分文章会告诉你,这是服务器在维护或者过载,高并发下一般会出现此状态值;

    严格来说,除非是DDoS攻击之类直接导致服务器宕机了,否则高并发并不会直接触发 503,而是触发 502 才对;

    参考上面的 502 复现场景,高并发最直接的影响是,没有足够的 PHP 进程来处理客户端请求,而一般NGINX承载的连接数是远远大于PHP-fpm的,所以问题大概率不是NGINX这里;

    如果想复现 NGINX-503 错误,可以通过设置 NGINX 的 连接数限制来复现;
    具体途径是:设置 limit_conn
    在NGINX配置文件中的 http 模块添加如下:
    limit_conn_zone $binary_remote_addr zone=per_ip:10m;
    意思是:对用户IP进行并发计数,将计数内存区命名为 per_ip,设置计数内存区大小为10MB;
    之后在 http 模块下的 server 模块添加类似如下限制:

    ## 完整配置demo
    http{
        limit_conn_zone $binary_remote_addr zone=per_ip:10m; 
        server {
            location /{
                limit_conn per_ip 3; # 限制用户ip的并发连接数为3
                root……
                index……
            }
        }
    }
    

    最后开启多线程,或者使用 ab 等压测工具,将并发数调到大于 3(因为上面的demo设置为最大连接数 3);
    然后去访问接口codetest.php,即可复现 503 错误。

    因此,常见的 503 大多是NGINX开启了并发连接数限制导致,比如,你的接口被爬虫抓取;
    如果是通过在PHP层通过redis限制访问频次,则可抛出自定义的错误,比如,401 等;
    所以高并发出现 503,并不是绝对的,需要辩证的去看待,这里只是列举了一种可能。

    504 复现

    504,Gateway Timeout,网关超时。

    它表示网关没有从上游及时获取响应数据。注意它和502在超时场景下的区别,502是指上游php-fpm因为超过自身允许的执行时间而不能正常生成响应数据,而504是指在php-fpm还未执行完成的某一时刻,由于超过了nginx自身的超时时间,nginx则以为上游php-fpm没有按照设置时间返回响应数据就会返回504, 此时对于php-fpm而言还会继续执行下去,直到执行完成。

    复现路径
    代码:
    sleep(15); echo 'hello world';
    php-fpm.conf
    request_terminate_timeout=30
    nginx
    fastcgi_read_timeout 5;
    codetest.php脚本执行时间需要15s,小于php-fpm设置的一次请求的超时时间30s,所以php脚本可正常完成;
    但nginx从php-fpm读取数据的超时时间为5s,所以在5s时,PHP未执行完成,但nginx的超时等待时间到了,于是返回504。

    nginx错误日志
    upstream timed out (110: Connection timed out) while reading response header from upstream

    Summary:

    • 499 是由于超过客户端设置的请求超时时间,客户端主动关闭连接;
    • 502 是由于 php-fpm 在自身的执行时间要求内无法按时完成,无法返给NGINX正常的响应值;
    • 504 是 php-fpm 在 NGINX 设置的超时时间内无法按时完成;
    • 503 大多由NGINX开启了连接数限制后的高并发原因产生;

    499,502,504,都是因超时而产生,区别在于,谁超了谁的时。
    499 是超了客户端本身的连接时间;
    502 是超了 php-fpm 的执行时间;
    504 是超了 NGINX 允许的最大读取时间。

    相关文章

      网友评论

          本文标题:HTTP状态码499,502,503,504的原理及复现

          本文链接:https://www.haomeiwen.com/subject/vdyjrdtx.html