为啥PHP需要异步操作?
一般来说PHP适用的场合是web页面展示等耗时比较短的任务如果对于比较花时间的操作如resize图片大数据导入批量发送EDMSMS等就很容易出现操作超时情况你可以说我可以设置无限超时时间等等你也要知道PHP有一个工作模式是fastcgiPHP无限不超时不代表fastcgi相应不超时……如果你还想说要fastcgi相应永不超时我建议你应该跟你们的运维人员讨论去……
这个时候异步的操作就发挥他的作用了由于是非阻塞操作操作会即时返回然后在后台再慢慢干活管你超时不超时的我就没有在当前的进程/线程下干活看吧是不是很美好不过其实这也是个坑……
PHP可以实现异步操作吗?
答案是肯定的不过网上各种的纯PHP实现得就有点别扭了socket模式挂起进程模式有的还直接fork进程很好各路神仙各显神通如果运维人员看到的话一定会×××××你们的不把web server跑死才怪……
那还有其他更好的方法去实现这个异步操作的可能么?有现在我们只有想怎么开外挂了查一下PECL主流的外挂方案有一堆的××MQ(消息队列)其中有个用于任务分配的外挂进入了我们的视线Gearman(其实这家伙才是角我就不详细介绍了点连接看介绍)
为啥选择Gearman?
别的不说就说他的client多支持很多语言的client你可以使用大部分你喜欢的语言去写worker我个人是很烦语言之争你喜欢用神码语言写worker都随你喜欢有数据持久化支持(就是把队列保存到数据库介质中那故障恢复也好做)有群集支持(其实很多××MQ都有这些功能)PECL上有扩展也有纯PHP实现扩展反正这个Gearman也活了很久了杂七杂八的问题都基本上解决了
基本思路
有了Gearman这外挂就简单多了就是向gearman发送一个任务把执行的任务发出去然后等待worker去调用PHP cli去运行我们的php代码
我就写了一下一个python的worker(别问我为啥用python我会pythonlinux下不用装runtime)你可以自己根据思路写一个PHP的worker不过嘛本人是不太信得过PHP跑的worker其他语言饭可以用javanodejs 或者其他语言实现一个worker试试对用Golang写worker有兴趣的朋友可以找我
然后到PHP的部分先上测试代码
<?php
require_once PHPAsyncClientphp;
date_default_timezone_set(Asia/Shanghai)
class AsyncTest {
const
LOG_FILE = /debuglog;
static public function run() {
if (PHPAsyncClient::in_callback(__FILE__)) {
self::log(php Async callback)
PHPAsyncClient::parse()
return;
}
if (PHPAsyncClient::is_main(__FILE__)) {
self::log(main run)
$async_call = PHPAsyncClient::getInstance()
$async_call>AsyncCall(AsyncTest callback array(
content => Hello World!!!
) array(
class => AsyncTest
method => callback
params => array(
content => Hello Callback!
)
) __FILE__)
return;
}
}
static public function callback($args) {
self::log(AsyncTest callback run)
self::log(AsyncTest callback args:print_r($args true))
}
static public function log($content) {
$fullname = dirname(__FILE__)self::LOG_FILE;
$content = date([Ymd H:i:s])$content\n;
file_put_contents($fullname $content FILE_APPEND)
}
}
AsyncTest::run()
就个静态方法一个是用于调试的log方法其他都是字面意思这个例子是对这种调用方式有个初步印象
结论
经过以上配置犀牛一样大的家伙后(要装一个Gearman还要跑个Py脚本)我们基本上就使PHP拥有了异步调用功能当然其中还有一个状态维护神马的要自己去实现所以发现其实这个方案不咋样太复杂了还是使用一些web service的方式去做web callback会好点(问题是web callback一样会超时……)这个请留意后续