熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> PHP編程 >> 正文

關於PHP實現異步操作的研究

2013-11-15 12:47:33  來源: PHP編程 

  為啥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一樣會超時……)這個請留意後續


From:http://tw.wingwit.com/Article/program/PHP/201311/21642.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.