PHP的非swoole异步操作

在前几天对WordPress进行同步更新文章的改造之后,每次更新文章都需要花费较长的时间,这很显然是不合理的.
更新文章主要都把时间花费在了一条shell指令上面.

1
exec('cd 目录 && hexo clean && hexo d && pm2 reload app');

引用原文地址:

  1. PHP实现异步调用方法研究
  2. PHP异步的的玩法

➡️先说说鸟哥文章中的几种玩法:

  1. 通过渲染前端页面,使用js执行Ajax,这种方式现在还适用。只是受限于业务场景,因为只能在浏览器中调用,遇到接口请求就不行了。

  2. 通过popen()方法打开一个指向进程的管道,每个请求会多起一个进程。忽略进程来看最主要的原因是数据的传输特别不方便,使用场景有限。

  3. 使用CURL扩展,通过设置timeout超时参数,能实现离弦之箭的效果。不过这种方法会主动断开连接。被调用的服务如果有做连接检测,也会中断服务端脚本的执行。比如我们请求 微信的某个费时接口(20s),我们调用1s就断开连接,微信端是否会维持请求执行20S是不可控的。所以在curl别的网站的时候这种方法不推荐大家使用,但如果只是curl自己还是很好用的。

  4. 与CURL类似,通过fsockopen创建socket连接访问远程服务,不循环获取请求结果。一样会有三中连接被断开的问题。

➡️PHP关于异步的改进

  1. CURL扩展已支持毫秒配置,将 CURLOPT_TIMEOUT 改为 CURLOPT_TIMEOUT_MS 即可生效(cURL 版本 >= libcurl/7.21.0,老服务器要检查版本),但还是我前面说的需要服务端配合,不然接口的调用成功失败不可控。

  2. CURL扩展已支持并发,我们能一次访问N个接口,执行时间取最长接口的时间。比如我们能一次访问 京东支付(1s),微信支付(1.2s),支付宝(0.8s)不同服务的三个接口,总耗时才1.2s。详细用法 curl_multi_init

  3. 类似Node.js的异步IO框架Swoole,能很好的实现异步调用;不过Swoole理论上不能算PHP框架,他算是PHP功能的扩展。所以除非项目都用Swoole写,不然也是享受不到异步IO的福利。

  4. 对yield的支持,能实现调度器的功能,写单进程的服务时能大展拳脚,特别是实现协程,异步更不在话下。不过在多进程的web服务上没有太大的使用场景,看未来会不会有新的玩法吧。

➡️关于web异步的解决方案

这个主要是针对那些需要异步而且并不太看中异步操作的结果的特殊场景

  1. curl配合较短的等待时间.
  2. 写一个swoole项目,需要异步时发送相应指令到相关端口
  3. 使用以下插件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
class Arrow{

static $instance;

/**
* @return static
*/
public static function getInstance(){
if (null == Arrow::$instance)
Arrow::$instance = new Arrow();
return Arrow::$instance;
}

public function run($rb){

$pid = pcntl_fork();
if($pid > 0){
pcntl_wait($status);
}elseif($pid == 0){
$cid = pcntl_fork();

if($cid == 0){
$rb();
}
exit();
}else
{
return true;
}
}
}
/**
*调用
*/
$time_out = 30;
Arrow::getInstance()->run(function() use ($time_out){
//这里写我们要执行的代码
sleep($time_out);
});

最终事实证明还是curl稳定,通过pcntl_fork()拉出的子进程和孙进程会影响到web的正常返回