Swoole定時隊列任務+消息推送

昨晚我躺在牀上,百無聊賴地翻閱 阿蘭·德波頓《身份的焦慮》這本書,看到這麼一段話,讓我想起網絡上作牆頭草的鍵盤俠,他們喜歡貼標籤,而後去簡單粗暴地批評或討好一類人,那麼能夠說公衆的眼睛是雪亮的嗎?我一直不喜歡太絕對太確定的觀點,對此我也保留懷疑,包括那些道聽途說來的道理。php

      公共輿論的缺陷,究其緣由,在於公衆不肯意將本身的觀點交由理性分析進行推敲,而是將本身的觀點創建在直覺、感情和習俗之上。web

    我常常在早餐出門上班的時候,會在微信小程序點一份麥當勞6元實惠早餐(酸菜雞肉粥+薯餅),而後路過的時候,順路取餐。redis

    可是我最近發現,麥當勞提供了 選擇取餐時間的服務。而後在對應的時間推進信息,提醒用戶取餐。數據庫

這麼作有兩個好處小程序

  • 保證客戶食物的新鮮微信小程序

  • 工做人員可按照時間去處理訂單微信

 

emmm  我以爲這是個好的商業idea。websocket

在吃完這份早餐,我就想,要不用代碼實現一個這個功能的demo吧。swoole

 

主要的工具網絡

  • swoole的websocket 服務端

  • swoole的異步毫秒定時器

  • redis 的有序集合

若是是在微信開發的話,其實調用一下微信的模板信息接口,進行消息推送。swoole_timer_after函數是一個一次性定時器,執行完成後就會銷燬。此函數與PHP標準庫提供的sleep函數不一樣,after是非阻塞的。而sleep調用後會致使當前的進程進入阻塞,將沒法處理新的請求。

使用redis 的有序集合能夠的實現按照取餐時間排序的隊列結構(圖我本身畫的),這裏我怕同一秒內有多個用戶下單,併發形成隊列的覆蓋,我選用了php獲取毫秒的內置函數()

microtime(true)//必定要加上ture才能返回浮點數據

餐廳的工做人員可按照上面的列表來

服務端生產隊列和異步推送信息的代碼實現

 1 <?php
 2 /**
 3  * Created by PhpStorm.
 4  * User: 印第安老斑鳩
 5  * Date: 2019/2/14
 6  * Time: 10:30
 7  */
 8 $server = new  swoole_websocket_server("0.0.0.0",9501);
 9 $server->set(array(
10     'worker_num'=>2,
11 ));
12 $redis = new redis();
13 $redis->connect('127.0.0.1', 6379);
14 $server->on('open', function (Swoole\WebSocket\Server $server, $request) {});
15 $server->on('message', function (Swoole\WebSocket\Server $server, $frame) use ($redis){
16     //將任務安裝時間丟進redis的有序集合之中(實際上要同步存進數據庫)
17     $result = $redis->zAdd('queue',microtime(true),'用戶user'.time());
18     if ($result){
19         swoole_timer_after($frame->data,function () use($frame,$server){
20             //作異常捕獲,失敗的話就通知失敗
21             try{
22                 $str = "你好,你在".(($frame->data)/1000).'秒前的預約的套餐,請到店內櫃檯前拿取';
23                 $server->push($frame->fd,$str);
24             }catch (Exception $exception){
25                 $server->push($frame->fd,'訂單失敗');
26             }
27         });
28     }
29     $server->push($frame->fd,"支付成功。請稍後,接收通知!");
30 });
31 $server->on('close', function ($ser, $fd) {
32     echo "client {$fd} closed\n";
33 });
34 $server->start();

 

定時任務消費隊列的代碼實現:

<?php
/**
 * Created by PhpStorm.
 * User: 印第安老斑鳩
 * Date: 2019/2/15
 * Time: 12:07
 */
$redis = new Redis();
$redis->connect('localhost',6379);
//3秒鐘查詢一次任務隊列
swoole_timer_tick(3000,function ()use($redis){
    $result = $redis->zRange('queue',0,-1);
    if($result){
        foreach ($result as $res){
            $redis->zRem("queue", $res);
            echo "隊列中的".$res."的訂單已經處理完畢\n";
        }
    }else{
        echo "目前沒有隊列訂單任務";
    }
});

測試結果:我建立了websocket 服務,端口是9501

 

啓動隊列的消費的進程,結果:

ok,就這麼一個demo搞定!但並不能投放於工業生產。

微信公衆號:

相關文章
相關標籤/搜索