首頁  >  文章  >  後端開發  >  非同步程式設計 - php如何非同步地執行程式碼?

非同步程式設計 - php如何非同步地執行程式碼?

WBOY
WBOY原創
2016-08-08 09:06:531297瀏覽

例如要記錄些日誌數據,我並不需要即時入庫,我想程式碼非同步執行後立刻執行下面的程式碼,我也不需要回調處理,如果把數據發給訊息佇列,這也需要時間吧,我想在毫秒就繼續下面的程式碼了,至於他把資料傳給誰,入庫花了多少時間我並不關心,舉個例子,
echo 1;
log(數據);
echo 2;
我想log函數後台執行,至於花多少時間,我不管,但是我不用去等他,對於我來說就是毫秒級執行完了似的。

回覆內容:

例如要記錄些日誌數據,我並不需要即時入庫,我想程式碼非同步執行後立刻執行下面的程式碼,我也不需要回調處理,如果把數據發給訊息佇列,這也需要時間吧,我想在毫秒就繼續下面的程式碼了,至於他把資料傳給誰,入庫花了多少時間我並不關心,舉個例子,
echo 1;
log(數據);
echo 2;
我想log函數後台執行,至於花多少時間,我不管,但是我不用去等他,對於我來說就是毫秒級執行完了似的。

發給訊息佇列 VS 毫秒等級 >>> 矛盾點在哪裡?

用 Redis 可以做隊列吧,Redis 操作每秒讀寫上萬次 ,你把訊息放到 Redis 裡面也就 1次寫操作吧,時間消耗低於毫秒吧。
所以我覺得 使用隊列,完全可以達到你說的毫秒級的需求吧。

另外,不管透過何種手段執行非同步操作,總是伴隨時間開銷,不可避免。

<code>//程序被阻塞10秒
shell_exec('timeout 10 vmstat 1 >/dev/null 2>&1 &');

//程序不会被阻塞
pclose(popen('timeout 10 vmstat 1 >/dev/null 2>&1 &', 'r'));

//因此可以异步执行任务
pclose(popen("timeout 60 php /path/to/task.php '$arg' >/dev/null 2>&1 &", 'r'));</code>

其中變數$arg是傳遞給腳本task.php的參數,task.php裡透過$argv[1]拿到這個參數.
timeout 60 表示task.php腳本的最大執行時間60秒,不需要的話可以去掉.
pclose(popen())實現異步的本質是打開一個進程去執行阻塞代碼,
適用於不要求執行完成後自動返回結果(回調)的異步場景.

字串參數$arg可以用單引號括起來,可以避免一些空格的影響,但還是有缺陷.
字串參數最好還是serialize序列化到文件,
然後給腳本task.php傳檔路徑這個參數,
讓task.php自己讀檔案unserialize反序列化拿資料.
檔案名稱應該做到唯一,例如可以是使用者ID或是進程PID加上時間隨機數:

<code>$filename = md5(uniqid($uid.'_',        true));
$filename = md5(uniqid($getmypid().'_', true));</code>
陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn