PHP 同步异步


同步

调用某个逻辑  等待该逻辑返回 调用结果

<?php 
$num = 30;
$result = model('content')->select();//伪代码,查询数据库
sleep(3);//伪代码,当成执行了3秒才返回
echo json_encode($result);//返回数据

只有 select查询 到数据时 才会返回数据给$result 这个值 是 数据库操作 完毕返回的值

<?php
$num = -30;
$result = abs($num);
echo json_encode($result);//返回数据

abs会返回数据给$result,这个值一定是abs正确操作的值


<?php
//模拟发送邮件中
$status = send();
sleep(30);//发送邮件花费30秒
echo "发送邮件".$status?'完成':'失败';

等待发送邮件的成功/失败 就是同步


异步

调用某个逻辑时 不等待 该逻辑返回的结果 只会返回 是否 已经调用的最初结果(或不返回)
调用 $.ajax() 默认情况下是异步ajax 它会继续往下执行代码 当有结果返回时 通过回调事件进行处理

<?php
$pid = pcntl_fork();
if ($pid == 0) {
//子进程
//模拟发送邮件
sleep(30);//发送邮件花费30秒
exit(0);
}
pcntl_waitpid($pid, $status, WNOHANG);
echo "发送邮件中";

通过新开一个进程去处理发送邮件的任务 在当前进程中 不关心 发送邮件的结果 直接往下执行


使用场景

当用户请求的结果比较慢 客户端又没有耐心等待 返回时 异步接口就显得很有优势
支付宝支付接口 当 发起支付的时候 支付宝系统 收到你的结果 通知你
支付成功后 异步接口确认处理完成

php 异步接口的实现
客户端 采用 AJAX 请求服务器
优点 简单 也最快 在返回给客户端的HTML代码中 嵌入AJAX调用 或 嵌入 img标签 src指向要执行的耗时脚本
缺点 Ajax都应该在onLoad以后触发 用户点开页面后 就关闭 那就不会触发的后台脚本了
使用img标签 用户浏览器会长时间等待 php脚本的执行完成 也就是用户浏览器的状态栏一直显示还在load

popen()函数
打开一个指向进程的管道 该进程由派生给定的 command 命令执行而产生
所以可以通过调用它 但忽略它的输出 使用代码如下
pclose(popen("/home/xinchen/backend.php &"  'r'));

优点 避免了第一个方法的缺点 并且也很快
缺点 不能通过HTTP协议请求另外的一个WebService
只能执行本地的脚本文件 并且只能单向打开 无法穿大量参数给被调用脚本 并且如果 访问量很高 会产生大量的进程 如果使用到了外部资源 还要自己考虑竞争

CURL扩展
$ch = curl_init();
$curl_opt = array(CURLOPT_URL, 'http://www.example.com/backend.php',CURLOPT_RETURNTRANSFER, 1,CURLOPT_TIMEOUT, 1,);
curl_setopt_array($ch, $curl_opt);
curl_exec($ch);
curl_close($ch);
缺点  由于使用CURL需要设置CUROPT_TIMEOUT为1 //最小为1 也就是说 客户端至少必须等待1秒钟

fscokopen()函数
fsockopen支持socket编程 可以使用fsockopen实现邮件发送等socket程序 使用fcockopen需要 手动拼接出header部分
参考 //cn.php.net/fsockopen/
$fp = fsockopen("www.cctv.com"  80  $errno  $errstr  30);
if (!$fp) {
    echo "$errstr ($errno)<br />\n";
} else {
    $out = "GET /index.php  / HTTP/1.1\r\n";
    $out .= "Host: www.cctv.com\r\n";
    $out .= "Connection: Close\r\n\r\n";
    fwrite($fp  $out);
    fclose($fp);
}

缺点 fscokopen 和popen 一样 并发非常多时会产生很多子进程 当达到apache的连接限制数时 就会挂掉

其他方式
比如tcp udp mqtt 等方式
MQTT(消息队列遥测传输)是ISO 标准(ISO/IEC PRF 20922)下基于发布/订阅范式的消息协议 mqtt 直接发布消息 连接数一般都很大
能满足很多需求 发布速度快 比较稳定 当订阅收到消息后会自动处理