zoukankan      html  css  js  c++  java
  • Swoole定时队列任务+消息推送

    昨晚我躺在床上,百无聊赖地翻阅 阿兰·德波顿《身份的焦虑》这本书,看到这么一段话,让我想起网络上做墙头草的键盘侠,他们喜欢贴标签,然后去简单粗暴地批评或讨好一类人,那么可以说公众的眼睛是雪亮的吗?我一直不喜欢太绝对太肯定的观点,对此我也保留怀疑,包括那些道听途说来的道理。

          公共舆论的缺陷,究其原因,在于公众不愿意将自己的观点交由理性分析进行推敲,而是将自己的观点建立在直觉、感情和习俗之上。

        我经常在早餐出门上班的时候,会在微信小程序点一份麦当劳6元实惠早餐(酸菜鸡肉粥+薯饼),然后路过的时候,顺路取餐。

        但是我最近发现,麦当劳提供了 选择取餐时间的服务。然后在对应的时间推动信息,提醒用户取餐。

    这么做有两个好处

    • 保证客户食物的新鲜

    • 工作人员可按照时间去处理订单

    emmm  我觉得这是个好的商业idea。

    在吃完这份早餐,我就想,要不用代码实现一个这个功能的demo吧。

    主要的工具

    • 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 (SwooleWebSocketServer $server, $request) {});
    15 $server->on('message', function (SwooleWebSocketServer $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
    ";
    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."的订单已经处理完毕
    ";
            }
        }else{
            echo "目前没有队列订单任务";
        }
    });

    测试结果:我创建了websocket 服务,端口是9501

    启动队列的消费的进程,结果:

    ok,就这么一个demo搞定!但并不能投放于工业生产。

    微信公众号:

  • 相关阅读:
    小星星短视频app
    多元思维模型整理--查理芒格---每本书的思维模型都要添加到这里
    张一鸣 南开大学演讲
    增长黑客特训营--入门
    深度学习 TensorFlow
    推荐算法之---FM算法;
    idea更改代码格式化快捷键
    centos7启动MySQL报 Job for mysqld.service failed because the control process exited with error code. See "systemctl status mysqld.service" and "journalctl -xe" for details.
    springboot启动报无法加载主类解决方法
    centos7搭建 mongodb 主从复制
  • 原文地址:https://www.cnblogs.com/zhengweizhao/p/10410511.html
Copyright © 2011-2022 走看看