• Nginx 499的问题


    PHP 异步 HTTP 与 NGINX 499

    PHP 异步 HTTP

    在 PHP 代码中提交异步 HTTP 请求比较常用的方式是通过 fsockopen/fwrite/fclose 来实现,请参考如下代码。

    function post($host, $path, $port, $data) {
        $post = http_build_query($data);
        $len = strlen($post);
    
        $fp = fsockopen($host, $port, $errno, $errstr, 30);
        if (!$fp) {
            echo "$errstr ($errno)
    ";
    
            return;
        }
    
        $out = "POST $path HTTP/1.1
    ";
        $out .= "Host: $host
    ";
        $out .= "Content-type: application/x-www-form-urlencoded
    ";
        $out .= "Connection: Close
    ";
        $out .= "Content-Length: $len
    ";
        $out .= "
    ";
        $out .= $post . "
    ";
        // echo($out);
        fwrite($fp, $out);
    
        // 注释掉如下代码实现不等待 HTTP 响应,从而实现“异步”
    //    $receive = '';
    //    while (!feof($fp)) {
    //        $receive .= fgets($fp, 128);
    //    }
    //    echo "<br />" . $receive;
    
    
        fclose($fp);
    }
    

    这段代码可以如期完成异步 HTTP 效果,但是如果提交的服务端有 NGINX 做 CGI 反代的话,可能会导致上游后端 PHP 接收不到该请求。

    NGINX 499

    查看 NGINX access log,发现这样的请求会以 499(Client Closed Request)记录。确定问题是因为:客户端主动端口请求连接时,NGINX 不会将该请求代理给上游服务(FastCGI PHP 进程),这个时候 access log 中会以 499 记录这个请求。

    要解决这个问题需要将 NGINX FastCGI 忽略客户端中断配置打开:

    fastcgi_ignore_client_abort on;
    

    这样无论客户端是否断开,都会将这个请求代理给上游,并且会记录上游服务处理后的返回状态。

    另外,还有一个类似配置 proxy_ignore_client_abort on;,这个配置是针对其他类型的反代,PHP 的场景并不适用。

    文章来源:https://hacpai.com/article/1444367397136?m=0

    备注:fastcgi_ignore_client_abort on;虽然会忽略客户端中断,只是在nginx记录中不记录499记录,并不能从根本上解决499问题。499有可能是客户端关闭连接,也有可能是请求时间超过upstream_response_time的值,但是即便是upstream_response_time没有值也会产生499,upstream_response_time 记录的是从 Nginx 把请求转发到后端服务器开始,到后端服务器响应到 Nginx 为止的时间。

    upstream_response_time 没有值有两种情况:

    1. 请求没有被转发到 upstream server

    2. Nginx 在等待 upstream response 的时候,客户端把连接关掉了,Nginx 也因此把跟 upstream 之间的连接关掉,所以不可能有 upstream response 被返回到 Nginx,自然也不会有 upstream_resposne_time.  在这种情况下,Nginx 会向客户端返回 499 。结合数据库中有记录来看,客户端发起一个 http 请求, 请求到 Nginx, Nginx 转发给后端 PHP,PHP 处理请求往数据库插记录,在这时,客户端发起 abort, Nginx 断开到 PHP 的连接,但是因为 PHP 已经发起了数据库的操作,这个操作不会被中断,所以记录被成功插入到数据库, Nginx 也向客户端返回了 499 端口。

        就大多数场景而言,如果只有少量的nginx499是无关紧要的,很大一部分只是客户端主动断开了请求而已。

    人生商业模式=能力(可怕的勤奋)+ 效率(效率,方法,工具)+杠杆(团队,产品,资本,影响力)
  • 相关阅读:
    Linux安装MySql
    Tomcat9配置SSL证书
    Linux安装Tomcat
    VMware安装Centos8
    Linux安装JDK
    mysql中utf8和utf8mb4区别
    MVVM模式
    深入浅析Node.js单线程模型
    同步异步阻塞非阻塞
    v-model
  • 原文地址:https://www.cnblogs.com/lovven/p/13111064.html
Copyright © 2020-2023  润新知