php 实时传输_php提前响应请求继续执行代码(伪异步)

在很多业务需求中,我们都可能需要先让php给浏览器输出,然后在后台慢慢处理其他不用输出耗时的业务.

那么,php该怎么实现这个功能呢?

ignore_user_abort(true);

首先,我们先来了解下ignore_user_abort(true);这个函数

这个函数可以忽略客户机的断开,继续执行php代码

那到底这个用来干啥的呢?例如://当用户A用浏览器请求下单逻辑

//由于后台逻辑非常多,需要处理20秒

//用户A等了10秒等不下去,关闭了网页

//默认情况下,用户关闭了网页,php进程则会直接终止,相当于执行了一半逻辑之后,停止了

//用户后面发现,自己已经有了这个订单数据,却没有订单详情(执行一半没来得及插入)

这个时候,ignore_user_abort就有用了,当忽略客户机断开后,php会一直执行,直到异常终止或已完成操作

set_time_limit(0);

在上面讲到,如果启用ignore_user_abort则会让php一直执行,直到异常终止,而在php常规web模式下,默认有个执行超时时间(30秒),当执行到30秒时,会直接终止该php进程,可使用set_time_limit(0),设置为用不超时,这样的话,客户端就算断开,就算超过30秒,php进程也会一直执行下去,直到执行完成

实时输出

在我之前的一篇讲buffer缓冲区的文章中,有讲到过浏览器实时输出,刷新缓冲区可以让php+web服务器的输出变成实时输出,不再需要等待脚本结束才显示内容.然而,apache和nginx的实现方式也有所不同

//apache方法,需要关闭apache缓冲区

for($i=0;$i<1000;$i++){

echo $i;

ob_flush();//刷新PHP自身缓冲区

flush();//刷新(特指apache)web服务器的缓冲区,输出数据

sleep(1);

}

//nginx缓冲区

ob_end_clean();

ob_implicit_flush();

header('X-Accel-Buffering: no'); // 关键是加了这一行。

for($i=0;$i<1000;$i++){

echo $i;

sleep(1);

}

用以上方法,就可以使php的echo,实时输出到浏览器中

伪结束响应

在认识到上面3种概念之后,我们就要开始实现这个功能了

伪结束响应原理是:

先让php提前输出"已结束响应"代码(其实还没有结束,还可以继续echo输出)

然后让用户自行关闭窗口,通过set_time_limit和ignore_user_abort函数实现php代码还在后台运行,如以下例子:<?php

//apache服务器

set_time_limit(0);

ignore_user_abort(true);

//巴拉巴拉这里处理了一些事情

echo "完成请求,3秒自动关闭页面(一段js自动关闭页面)";

ob_flush();//刷新PHP自身缓冲区

flush();//刷新(特指apache)web服务器的缓冲区,输出数据

//这里还在巴拉巴拉处理事情\

$i=0;

while(1){

//注意,死循环非常危险,会造成该web进程一直在处理,不会退出,永久占用一个进程,而且管理该进程非常麻烦,建议加个判断啥的

file_put_contents('test.txt',$i);

$i++;

sleep(1);

}

//nginx服务器

set_time_limit(0);

ignore_user_abort(true);

//巴拉巴拉这里处理了一些事情

ob_end_clean();

ob_implicit_flush();

header('X-Accel-Buffering: no'); // 关键是加了这一行。

echo "完成请求,3秒自动关闭页面(一段js自动关闭页面)";

//这里还在巴拉巴拉处理事情\

$i=0;

while($i<100){

//注意,死循环非常危险,会造成该web进程一直在处理,不会退出,永久占用一个进程,而且管理该进程非常麻烦,建议加个判断啥的

file_put_contents('test.txt',$i);

$i++;

sleep(1);

}

提前结束响应

在php-fpm中,有个函数fastcgi_finish_request可使得web服务器提前中断http响应:<?php

//php-fpm模式下

set_time_limit(0);

ignore_user_abort(true);

//巴拉巴拉这里处理了一些事情

echo "完成请求,3秒自动关闭页面(一段js自动关闭页面)";

fastcgi_finish_request();//真正的结束响应,后面的echo将不起作用

//这里还在巴拉巴拉处理事情

$i=0;

while($i<100){

//注意,死循环非常危险,会造成该web进程一直在处理,不会退出,永久占用一个进程,而且管理该进程非常麻烦,建议加个判断啥的

file_put_contents('test.txt',$i);

$i++;

sleep(1);

}

在非fpm模式下,该怎么提前中断呢?<?php

//非php-fpm  一般是apache

set_time_limit(0);

ignore_user_abort(true);

ob_end_flush();

ob_start();

//巴拉巴拉这里处理了一些事情

echo '完成请求,3秒自动关闭页面(一段js自动关闭页面)';

header("Content-Type: text/html;charset=utf-8");

header("Connection: close");//告诉浏览器不需要保持长连接

header('Content-Length: '. ob_get_length());//告诉浏览器本次响应的数据大小只有上面的echo那么多

ob_flush();

flush();

//header不会经过buffer,直接输出到浏览器,浏览器接收到之后,直接主动关闭连接

//这里还在巴拉巴拉处理事情

$i=0;

while($i<100){

//注意,死循环非常危险,会造成该web进程一直在处理,不会退出,永久占用一个进程,而且管理该进程非常麻烦,建议加个判断啥的

file_put_contents('test.txt',$i);

$i++;

sleep(1);

}

本文为仙士可原创文章,转载无需和我联系,但请注明来自仙士可博客www.php20.cn

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实现支付异步回调通知机制可以分为以下几个步骤: 1. 在支付接口中设置回调通知地址,当支付完成后,支付平台会向该地址发送回调通知请求。 2. 在接收到回调通知请求时,首先需要验证该请求的合法性。可以通过验证请求参数的签名、订单号等信息来确保请求的合法性。 3. 验证通过后,需要更新订单状态,将订单状态改为已支付,并记录支付平台返回的交易号等信息。 4. 最后,需要向支付平台返回一个成功的响应,通知支付平台该回调通知已经处理完毕。 以下是一个简单的 PHP 实现示例: ```php <?php // 验证请求的合法性 $sign = $_POST['sign']; // 签名 $order_no = $_POST['order_no']; // 订单号 $amount = $_POST['amount']; // 支付金额 $transaction_id = $_POST['transaction_id']; // 交易号 if (verify_sign($sign, $order_no, $amount)) { // 更新订单状态 update_order_status($order_no, $amount, $transaction_id); // 返回成功响应 echo 'success'; } else { // 返回失败响应 echo 'fail'; } // 验证签名 function verify_sign($sign, $order_no, $amount) { // TODO: 实现签名验证逻辑 } // 更新订单状态 function update_order_status($order_no, $amount, $transaction_id) { // TODO: 更新订单状态逻辑 } ?> ``` 注意,以上代码仅为示例,实际的实现方式可能因支付平台的不同而有所差异。同时,为了确保支付安全,建议使用 HTTPS 协议来传输回调通知请求响应

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值