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)\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 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是无关紧要的,很大一部分只是客户端主动断开了请求而已。

Nginx 499的问题的更多相关文章

  1. Nginx 499错误的原因及解决方法

    今天进行系统维护,发现了大量的499错误, 499错误 ngx_string(ngx_http_error_495_page), /* 495, https certificate error */n ...

  2. nginx 499状态码

    Web服务器在用着nginx,在日志中偶尔会看到有499这个错误. rfc2616中,400-500间的错误码仅定义到了417,所以499应该是nginx自己定义的.后来想到读读nginx代码,疑问立 ...

  3. 通过nginx 499 来判断服务端超时数量

    这个其实不能算一篇文章,因为内容太少了,就当记点笔记吧. (1)什么是 nginx 499 499 其实是 nginx 下特有的 http 状态码,代表客户端主动断开了连接,导致服务器无法返回 htt ...

  4. nginx 499 状态码优化

    在grafana界面中发现不少499的状态码,在网上了解到出现499的原因大体都是说服务端处理时间过长,客户端主动关闭了连接.   既然原因可能是服务端处理时间太长了,看一下upstream_resp ...

  5. nginx 499 错误码

    今天查看nginx的access log 文件,发现类似这种请求: [22/Apr/2014:14:01:12 +0800] "GET / HTTP/1.1" 499 0 &quo ...

  6. nginx 499错误

    原因: 服务响应时间太长,客户端自动断开链接. 解决: 1. 找到响应世间长的接口,看依赖的数据源(数据库,第三方接口等)响应时间是否超时,还是自己程序有逻辑问题. 可以通过加入日志打印时间消耗来确定 ...

  7. Nginx_HTTP 499 状态码 nginx下 499错误

    日志记录中HTTP状态码出现499错误有多种情况,我遇到的一种情况是nginx反代到一个永远打不开的后端,就这样了,日志状态记录是499.发送字节数是0. 老是有用户反映网站系统时好时坏,因为线上的产 ...

  8. HTTP 499 状态码 nginx下 499错误[转]

    日志记录中HTTP状态码出现499错误有多种情况,我遇到的一种情况是nginx反代到一个永远打不开的后端,就这样了,日志状态记录是499.发送字节数是0. 老是有用户反映网站系统时好时坏,因为线上的产 ...

  9. HTTP 499 状态码 nginx下 499错误

    日志记录中HTTP状态码出现499错误有多种情况,我遇到的一种情况是nginx反代到一个永远打不开的后端,就这样了,日志状态记录是499.发送字节数是0. 老是有用户反映网站系统时好时坏,因为线上的产 ...

随机推荐

  1. 解决go mod或go get时`x509: certificate signed by unknown authority`错误

    一般go get私有仓库时会出现如下错误: go: xxx@v0.0.0-20190918102752-bb51b27911ca: unrecognized import path "xxx ...

  2. 通过ADB调试安卓程序

    ADB,即 Android Debug Bridge,它是Android开发/测试人员不可替代的强大工具. 1.下载ADB后,将以下四个文件放到某个文件夹下即可.因为打开Cmd默认路径是 C:\Use ...

  3. Sql语句知识大全

    1.经典SQL语句大全(绝对的经典) 2. 3. 4.一.基础 1.1.说明:创建数据库 2.CREATE DATABASE database-name 3.2.说明:删除数据库 4.drop dat ...

  4. android项目笔记整理(3)

    61.AlphabetIndexer字母索引辅助类       实现对链表类型的数据进行快速索引. 应用于类似联系人列表右侧的导航栏 注意:       1.链表里的元素必须是Object类型,并实现 ...

  5. static{}静态代码块与{}普通代码块之间的区别

    先看一个例子: //class A package com.my.test; class A { static { System.out.println("A1:父类静态代码区域" ...

  6. vue父组件传值和子组件触发父组件方法

    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script> <scr ...

  7. Shell中比较判断

    一.shell判断数组中是否包含某个元素:ary=(1 2 3)a=2if [[ "${ary[@]}" =~ "$a" ]] ; then    echo & ...

  8. 【loj#6220】sum

    题目传送门:https://loj.ac/problem/6220 题意:对于一个序列$a$,找出它的一个子序列$b$,使$\sum_{a_i \in b}a_i \equiv 0 \pmod n$ ...

  9. linux下安装db2

    最近研究了一下在 ubuntu下安装db2的过程,很快就完成安装,特贴出来供大家讨论,如有错误请多多指教. 注意:安装过程请使用root用户,否则会出现安装失败的情况: 安装过程: 准备工作: 准备安 ...

  10. java lambda 所有列求和

    今天做东西的时候遇到一个需求,求list集合所有列的求和.折腾半天也没有搞出来,网上大部分都是单列求和就像下面这样的,其他都差多,什么 min,max avg count 只得到了number这个属性 ...