1.为啥PHP需要异步操作?
一般来说PHP适用的场合是web页面展示等耗时比较短的任务,如果对于比较花时间的操作如resize图片、大数据导入、批量发送EDM、SMS等,就很容易出现操作超时情况。你可以说我可以设置无限超时时间,等等你也要知道PHP有一个工作模式是fastcgi,PHP无限不超时,不代表fastcgi相应不超时……如果你还想说要fastcgi相应永不超时,我建议你应该跟你们的运维人员讨论去……
这个时候异步的操作就发挥他的作用了,由于是非阻塞操作,操作会即时返回,然后在后台再慢慢干活。管你超时不超时的,我就没有在当前的进程/线程下干活。看吧是不是很美好,不过其实这也是个坑……
2.PHP可以实现异步操作吗?
答案是肯定的,不过网上各种的纯PHP实现得就有点别扭了。socket模式、挂起进程模式、有的还直接fork进程。很好,各路神仙各显神通。如果运维人员看到的话,一定会×××××你们的,不把web server跑死才怪……
那还有其他更好的方法去实现这个异步操作的可能么?有,现在我们只有想怎么开外挂了。查一下PECL主流的外挂方案有一堆的××MQ(消息队列),其中有个用于任务分配的外挂进入了我们的视线Gearman(其实这家伙才是角,我就不详细介绍了,点连接看介绍)。
3.为啥选择Gearman?
别的不说,就说他的client多,支持很多语言的client,你可以使用大部分你喜欢的语言去写worker。我个人是很烦语言之争,你喜欢用神码语言写worker都随你喜欢。有数据持久化支持(就是把队列保存到数据库介质中,那故障恢复也好做),有群集支持(其实很多××MQ都有这些功能)。PECL上有扩展,也有纯PHP实现扩展。反正这个Gearman也活了很久了,杂七杂八的问题都基本上解决了。
4.基本思路
有了Gearman这外挂就简单多了。就是向gearman发送一个任务,把执行的任务发出去,然后等待worker去调用PHP cli去运行我们的php代码。
我就写了一下一个python的worker(别问我为啥用python,1.我会python,2.linux下不用装runtime),你可以自己根据思路写一个PHP的worker,不过嘛,本人是不太信得过PHP跑的worker。其他语言饭可以用java、node.js 或者其他语言实现一个worker试试。对用Golang写worker有兴趣的朋友可以找我。
phpasync_worker_py
不好意思,里面是没有注释的。一个配置文件,一个py脚本。基本的功能也就是分析一下调用的参数,然后调用PHP Cli,就是那样子而已。要让py脚本跑起来请自行安装python的gearman模块。
然后到PHP的部分先上测试代码:
复制代码 代码如下:
<?php
require_once 'PHPAsyncClient.php';
date_default_timezone_set('Asia/Shanghai');
class AsyncTest {
const
LOG_FILE = '/debug.log';
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('[Y-m-d H:i:s]').$content."\n";
file_put_contents($fullname, $content, FILE_APPEND);
}
}
AsyncTest::run();
就3个静态方法,一个是用于调试的log方法,其他都是字面意思。这个例子是对这种调用方式有个初步印象。然后直接上PHP的所有源码:
php_async.zip
然后应该会有很多人会说,win下安装不了gearman……所以我把java版的gearman server也放上去吧。
java-gearman-service-0.6.6.zip
5.结论
经过以上配置犀牛一样大的家伙后(要装一个Gearman,还要跑个Py脚本),我们基本上就使PHP拥有了异步调用功能,当然其中还有一个状态维护神马的要自己去实现。所以发现,其实这个方案不咋样,太复杂了。还是使用一些web service的方式去做web callback会好点(问题是web callback一样会超时……),这个请留意后续。
为防止上面的代码无法下载,特打包下载
原文链接:http://my.oschina.net/wakanoc/blog/101789
异步操作
免责声明:本站文章均来自网站采集或用户投稿,网站不提供任何软件下载或自行开发的软件! 如有用户或公司发现本站内容信息存在侵权行为,请邮件告知! 858582#qq.com
《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线
暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。
艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。
《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。