摘要:六隊(duì)列具體實(shí)現(xiàn)三寫執(zhí)行隊(duì)列的程序根據(jù)設(shè)計(jì),執(zhí)行隊(duì)列的程序文件是,它的主要功能是把任務(wù)從隊(duì)列表里取出來,并且在后臺執(zhí)行。八服務(wù)器部署一配置咱們執(zhí)行隊(duì)列的程序都寫好了,這個程序怎么觸發(fā)呢,當(dāng)然就要用到的定時任務(wù),每隔一定的時間,執(zhí)行一次。
六、隊(duì)列具體實(shí)現(xiàn)三:寫執(zhí)行隊(duì)列的程序
根據(jù)設(shè)計(jì),執(zhí)行隊(duì)列的程序文件是 do_queue.php , 它的主要功能是把任務(wù)從隊(duì)列表里取出來,并且在后臺執(zhí)行。
do_queue.php部分代碼:
$phpcmd = exec("which php"); //查找到php安裝位置 $cqueue = new Queue(); $tasks = $cqueue->getQueueTask(200); foreach ($tasks as $t) { $taskphp = $t["taskphp"]; $param = $t["param"]; $job = $phpcmd . " " . escapeshellarg($taskphp) . " " . escapeshellarg($param); system($job); }
七、具體任務(wù)的業(yè)務(wù)實(shí)現(xiàn)
還是拿群發(fā)消息來做例子,我們需要寫好一個群發(fā)消息的程序,這個程序接收事先定義好的參數(shù),然后根據(jù)參數(shù)調(diào)用發(fā)消息的接口把消息發(fā)送出去。
這個一般由做業(yè)務(wù)功能的工程師實(shí)現(xiàn)。但是架構(gòu)師事先得寫文檔例子,教會別人使用。
send_msg.php:
$para = $argv[1]; $arr = unserialize($para); $cmessage = new Message(); foreach($arr["uids"] as $touid) { $cmessage->send($arr["uid"], $touid, $arr["content"]); }
八、服務(wù)器部署一:配置crontab
咱們執(zhí)行隊(duì)列的程序都寫好了, 這個程序怎么觸發(fā)呢,當(dāng)然就要用到linux的定時任務(wù),每隔一定的時間,執(zhí)行do_queue.php一次。但是呢,這里不是直接調(diào)用do_queue.php,咱們再提高一層,加個調(diào)度程序cron_mission.php, 在cron_mission.php里面調(diào)用do_queue.php
配置定時任務(wù) crontab:
l crontab –e
l * * * * * cd /ucai/schedule;php cron_mission.php >> cron_mission.log
九、服務(wù)器部署二:寫定時任務(wù)調(diào)度程序
思路:將定時任務(wù)寫入到任務(wù)調(diào)度程序cron_mission.php中,這樣可以在cron_mission.php中靈活控制隊(duì)列任務(wù)。相比較直接通過crontab控制doQueue.php而言,避免了頻繁修改服務(wù)器上的crontab,從安全,便于維護(hù)等角度來說,都是上策。
cron_mission.php 示例:
if ($minute % 5 == 0) { if(chdir($site_dir."app/")) { $cmd = "$phpcmd do_queue.php > do_queue.log &"; echo "[" , $ymd , " " , $hour , ":" , $minute , "] " , $cmd , "n"; system($cmd); } }
十、開啟多進(jìn)程并發(fā)執(zhí)行隊(duì)列
思路:對任務(wù)序列進(jìn)行編號,數(shù)據(jù)庫中執(zhí)行的時候
where條件加上id%每個隊(duì)列要執(zhí)行任務(wù)總數(shù)=隊(duì)列編號
這樣可以避免重復(fù)處理
例如:每個進(jìn)程執(zhí)行10條任務(wù),修改如下
1:定時任務(wù)的修改
修改前:
if ($minute % 5 == 0) { if(chdir($site_dir."app/")) { $cmd = "$phpcmd do_queue.php > do_queue.log &"; echo "[" , $ymd , " " , $hour , ":" , $minute , "] " , $cmd , "n"; system($cmd); } }
修改后:
if ($minute % 5 == 0) { for ($i=0; $i < 10; $i++) { $cmd = "$phpcmd doQueue.php 10 $i>> doQueueMission".date("Y-m-d").".log "; echo date("Y-m-d H:i:s") . "t : " .$cmd."n"; system($cmd); } }
//每次進(jìn)行10個進(jìn)程,$i來區(qū)分是當(dāng)前的進(jìn)程標(biāo)示
2:隊(duì)列執(zhí)行程序的修改
修改前:
$phpcmd = "D:workwampbinphpphp5.3.10php "; $cqueue = new Queue(); $tasks = $cqueue->getQueueTask(200);
修改后:
$phpcmd = "D:workwampbinphpphp5.3.10php "; $total=$argv[1]; $i=$argb[2]; $cqueue = new Queue(); $tasks = $cqueue->getQueueTask($total,$i,200);
3:取隊(duì)列接口的修改
public function getQueueTask($limit = 1000) { $limit = (int)$limit; $sql = "select id, taskphp, param from queue where status = 0 order by id asc"; $re = query($sql); return $re; }
修改后:
public function getQueueTask($total,$i,$limit = 1000) { $limit = (int)$limit; $sql = "select id, taskphp, param from queue where status = 0 and id%$total=$i order by id asc"; $re = query($sql); return $re; }
4:需要關(guān)注服務(wù)器壓力
進(jìn)程數(shù)定為多少,取決于服務(wù)器壓力
十一、實(shí)現(xiàn)任務(wù)優(yōu)先級
1:任務(wù)存儲表加優(yōu)先級字段
在數(shù)據(jù)表里,加一個優(yōu)先級字段,按字段值的數(shù)值大小來區(qū)分優(yōu)先級
2:修改取隊(duì)列任務(wù)接口,按優(yōu)先級取
同樣是在sql語句中增加order by
十二、記錄隊(duì)列日志
1:關(guān)鍵地方加echo
2:shell腳本的>>和>的各自作用
總結(jié):
我們這里的隊(duì)列實(shí)現(xiàn)借助了服務(wù)器的計(jì)劃任務(wù)來實(shí)現(xiàn),例如linux中的crontab,這本身是linux系統(tǒng)中的一個程序,平時我們還可以使用他來進(jìn)行定時執(zhí)行.sh腳本,例如將數(shù)據(jù)庫備份打包并ftp傳送到指定服務(wù)器上,這個功能不需要借助php腳本,直接用.sh腳本就可以實(shí)現(xiàn)。在這里我們巧妙的將crontab和php腳本結(jié)合,并且使用crontab來不斷調(diào)用一個隊(duì)列調(diào)度接口cronMission.php,再通過cronMission.php直接來控制具體什么時候或者是滿足什么條件來執(zhí)行什么隊(duì)列任務(wù)。
這里面幾個需要注意的地方
1:往數(shù)據(jù)庫中存取數(shù)據(jù)時,不要直接使用json_encode或者json_decode,容易造成一些意外問題,在代碼中,我們定義了a2s和s2a兩個方法,分別是處理數(shù)組轉(zhuǎn)為字符串,和從數(shù)據(jù)庫中讀取字符串后轉(zhuǎn)為數(shù)組。
2:當(dāng)任務(wù)量比較大,同時服務(wù)器負(fù)載又沒有充分利用的時候,可以使用多進(jìn)程并發(fā)處理,在并發(fā)處理的時候需要考慮一個問題,就是如何避免重復(fù),在這里我們使用了,對隊(duì)列任務(wù)進(jìn)行標(biāo)記,每次從數(shù)據(jù)庫中讀取一個進(jìn)程需要處理的一批任務(wù),使用數(shù)據(jù)庫中id與批次標(biāo)示取余等于0的方法來區(qū)分,避免不同批次的隊(duì)列,重復(fù)處理相同任務(wù)。(上面步驟10中有具體實(shí)現(xiàn))
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/20761.html
摘要:而事件循環(huán)是主線程中執(zhí)行棧里的代碼執(zhí)行完畢之后,才開始執(zhí)行的。由此產(chǎn)生的異步事件執(zhí)行會作為任務(wù)隊(duì)列掛在當(dāng)前循環(huán)的末尾執(zhí)行。在下,觀察者基于監(jiān)聽事件的完成情況在下基于多線程創(chuàng)建。 主要問題: 1、JS引擎是單線程,如何完成事件循環(huán)的? 2、定時器函數(shù)為什么計(jì)時不準(zhǔn)確? 3、回調(diào)與異步,有什么聯(lián)系和不同? 4、ES6的事件循環(huán)有什么變化?Node中呢? 5、異步控制有什么難點(diǎn)?有什么解決方...
摘要:諸如此類,隊(duì)列的應(yīng)用范圍是如此之廣。方案抽象到更高一層,開發(fā)一套通用異步處理隊(duì)列適用于任何復(fù)雜的業(yè)務(wù)邏輯那么,作為架構(gòu)師,使用隊(duì)列的做法,將抽象層和業(yè)務(wù)層分離,可具有良好的擴(kuò)展性和可維護(hù)性。 一、隊(duì)列使用場景:為什么需要隊(duì)列 在web開發(fā)中,我們經(jīng)常會遇到需要處理批量任務(wù)的時候,這些批量任務(wù)可能是用戶提交的,也可能是當(dāng)系統(tǒng)被某個事件觸發(fā)時需要進(jìn)行批量處理的,面對這樣的任務(wù),如果是用戶提...
摘要:可變隊(duì)列會對長期沒有更新動態(tài)的那部分不活躍用戶進(jìn)行減緩速度,減緩對他們微博的獲取頻率,同時加大對活躍用戶的獲取頻率。 注:本文為轉(zhuǎn)載,原文請查看star7th的個人博客。 一、什么是 HTQ 先介紹下基本概念。 我們在編寫程序時,偶爾會遇到需要用到異步隊(duì)列的情況。比如說,我發(fā)送一萬封郵件,如果單純使用一個for循環(huán)來發(fā)送,則執(zhí)行時間要很長,要等很久才能發(fā)完,同時很容易導(dǎo)致阻塞、超時等問...
摘要:在異步機(jī)制中,任務(wù)隊(duì)列就是用來維護(hù)異步任務(wù)回調(diào)函數(shù)的隊(duì)列。四對象對象是工作組提出的一種規(guī)范,目的是為異步編程提供統(tǒng)一接口。 異步 1.JavaScript單線程的理解 Javascript語言的執(zhí)行環(huán)境是單線程(single thread)。所謂單線程,就是指一次只能完成一件任務(wù)。如果有多個任務(wù),就必須排隊(duì),前面一個任務(wù)完成,再執(zhí)行后面一個任務(wù),以此類推。 2.JavaScript單線...
摘要:的執(zhí)行機(jī)制就是一個主線程一個任務(wù)隊(duì)列。同步任務(wù)就是放在主線程上執(zhí)行的任務(wù),異步任務(wù)就是放在任務(wù)隊(duì)列的任務(wù)。和上述運(yùn)行的機(jī)制主要說明的是,而的出現(xiàn)及普及,又有了新的概念,,它的出現(xiàn),進(jìn)一步,中分為兩種任務(wù)類型和,在中,稱為,可稱為。 上一篇文章主要整理了一下js引擎是如何工作的,這篇文章主要整理js的事件循環(huán)Event loop,以及異步編程的原理 事件循環(huán)Event loop 之前文章...
閱讀 1791·2021-11-11 11:02
閱讀 1697·2021-09-22 15:55
閱讀 2499·2021-09-22 15:18
閱讀 3500·2019-08-29 11:26
閱讀 3757·2019-08-26 13:43
閱讀 2656·2019-08-26 13:32
閱讀 912·2019-08-26 10:55
閱讀 973·2019-08-26 10:27