Nginx 499的问题

PHP 异步 HTTP 与 NGINX 499

PHP 异步 HTTP

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

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)\n"; return; } $out = "POST $path HTTP/1.1\r\n"; $out .= "Host: $host\r\n"; $out .= "Content-type: application/x-www-form-urlencoded\r\n"; $out .= "Connection: Close\r\n"; $out .= "Content-Length: $len\r\n"; $out .= "\r\n"; $out .= $post . "\r\n"; // echo($out); fwrite($fp, $out); // 注释掉以下代码实现不等待 HTTP 响应,从而实现“异步” // $receive = ''; // while (!feof($fp)) { // $receive .= fgets($fp, 128); // } // echo "<br />" . $receive; fclose($fp); } 

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

NGINX 499

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

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

fastcgi_ignore_client_abort on; 

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

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

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

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

upstream_response_time 没有值有两种状况:post

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

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

    就大多数场景而言,若是只有少许的nginx499是可有可无的,很大一部分只是客户端主动断开了请求而已。

相关文章
相关标签/搜索