• 初识 Rabbitmq


     
     
     

    这里我主要讲述自己安装和测试使用的大概流程,概念性的东西不做过多介绍,大家可以自行百度,资料也比较多。

    这里我主要阐述的是 centos7 下面的安装方法,不过windows的也大同小异

    首先、  RabbitMQ是 AMQP 协议的 Erlang 的实现,是由Erlang语言编写的,所以首先我们要安装 Erlang 语言。

      大家可以参考  https://www.jianshu.com/p/95a720e6c955  这个地址的安装流程。

      需要注意的就是版本不要太老,不然可能下面安装 rabbitmq 的时候会提示错误

    接下来就是安装 rabbitmq 了,这里的细节网上也比较多,我自己的话也是参考别人的,然后走了一些坑,看了好几篇才顺利完成。

      https://www.cnblogs.com/fengyumeng/p/11133924.html  这里随便贴一个可参考的。

      这里会遇到一些问题,可能是上面你的 erlang 版本太老的问题,其他的问题倒是比较少。

      安装成功之后是可以从端口  localhost:15672  看到mq的管理页面的,账号密码默认为 guest,因为是纯英文界面,可能刚开始看起来比较吃力,推荐大家多看下 rabbitmq 的介绍和管理,等测试通了大概就了解了。

    然后就是和编程语言对接了。犹豫由于本人是做php的,所以专门讲解 php 下使用mq的流程:

      1、安装 ampq 扩展

        https://www.cnblogs.com/brady-wang/p/13742032.html  这里也是随便贴一篇吧,都是大同小异,大家要注意的就是扩展和php的版本对应问题。windows下就更简单了,直接下载dll文件。

      2、代码测试

        这里我主要介绍  php-amqplib 的使用,大家可以使用 composer 去下载 “ composer require php-amqplib/php-amqplib --ignore-platform-reqs ”

        客户端代码: ( 这里是我框架里面封装好的,大家也可以根据自己情况直接把代码提出来,单个文件测试 )

        

    <?php
    namespace AppHttpControllers;
    
    
    use AppSupportTcp;
    use IlluminateHttpRequest;
    use PhpAmqpLibConnectionAMQPStreamConnection;
    use PhpAmqpLibMessageAMQPMessage;
    
    class RabbitMq
    {
    
        public function mq_send(Request $request)
        {
            $connection = new AMQPStreamConnection('localhost', 5672, 'guest', 'guest','/');
            $channel = $connection->channel();
            $channel->queue_declare('hello', false, false, false, false);
    
            $msg_str = [];
            for($i=1;$i<20;$i++)
            {
                $str = '发送消息'.time().'-'.rand(1,1000000);
                $msg = new AMQPMessage($str);
                $channel->basic_publish($msg, '', 'hello');
    
                $msg_str[] = " [x] Sent $str";
            }
    
    
            $channel->close();
            $connection->close();
    
        }
    
    }

        服务端代码:( 需要用 CLI 模式运行 )

        

    <?php
    
    use PhpAmqpLibConnectionAMQPStreamConnection;
    
    require __DIR__.'/../vendor/autoload.php';
    $connection = new AMQPStreamConnection('localhost', 5672, 'guest', 'guest', '/');
    $channel = $connection->channel();
    $channel->queue_declare('hello', false, false, false, false);
    
    //            echo ' [*] Waiting for messages. To exit press CTRL+C', "
    ";
    
    $callback = function ($msg) {
    //                echo " [x] Received ", $msg->body, "
    ";
    };
    
    $channel->basic_consume('hello', '', false, true, false, false, $callback);
    
    while (count($channel->callbacks)) {
    $channel->wait();
    }
    
    $channel->close();
    $connection->close();

        这里主要是介绍怎么使用和测试,具体的代码逻辑和使用大家可自行百度其他文档,因为东西比较散,难度不高。也就是一个 生产者->消费者 的模型,一个推送,一个监听消费的意思,当然里面路由还是比较丰富的,有兴趣的可以多深究一些。

        我们理解这些扩展的时候,不防把mysql甚至redis等的使用联系到一起,其实都是创建连接,然后调用方法使用,也没有说多复杂,真正复杂的是我们怎么把他融入到我们项目中使用。

        

        这里只讲一个问题。

          由于生产者可以直接嵌入到我们的api里面,直接http请求就可以执行生产消息,这里倒没有太多要说的了,可根据自己项目自行封装

          那么消费者因为是 cli 运行模式来监听的,那么我们就不能用传统的api方式去做了,而且也不合适,因为要时时监听。这里可以想到的有好几种,比方说 crontab 定时任务,但是linux 定时任务只能做到分钟级,或者可以借助 workman或者swoole做到秒级毫

        秒级等等,又或者写 php  demo.php  start 等,但是关闭当前xshell窗口可能进程就失效了。这里我主要用到的是 php监听脚本+shell脚本 的方式,有兴趣的同学可以详细看一下  https://zhuanlan.zhihu.com/p/52965561 这篇文章。

         

        具体实现逻辑:

          1.  创建php监听脚本,子进程数量可自行控制,加载好业务代码,测试通即可。 这里附带一下我个人的demo,可供参考

          

    <?php
    
    
    use PhpAmqpLibConnectionAMQPStreamConnection;
    
    function daemon()
    {
    
        global $child;
        //1.1 创建子进程
        $pid = pcntl_fork();
        switch($pid){
            case -1:
                exit("Fork failed");
                break;
            case 0: //child
                //2、设置sid
                if(($sid = posix_setsid()) <= 0){
                    die("Set sid failed!
    ");
                }
    
                //3、改变目录
                if(chdir('/') === false){
                    die("Change directory failed!
    ");
                }
    
                //4、更改为宽松掩码
                umask(0);
    
                //5、关闭标准I/O
                fclose(STDIN);
                //fclose(STDOUT);
                //fclose(STDERR);
                break;
    
            default:        //parent
                exit;
                break;
        }
    
    }
    
    $sign = $_SERVER['argv'][1];
    switch($sign){
    
        case 'start':
            if(file_exists('/tmp/masterPid')){
                die("MasterPid already running!");
            }
            break;
    
        case 'stop':
    
            $masterPid = file_get_contents('/tmp/masterPid');
            exec("ps --ppid {$masterPid} | awk '/[0-9]/{print $1}'",$output,$status);
            if($status == 0){
                print_r($output);
            }
            break;
    
        case 'reload':
            break;
    
        default:
            die("Please enter commond...
    ");
            break;
    
    }
    
    daemon();
    
    $child = [];
    
    $masterPid = posix_getpid();
    file_put_contents('/tmp/masterPid',$masterPid);//存放主进程ID
    
    function forkPro()
    {
        global $child;
    
        //echo "Master process id: " . posix_getpid() . PHP_EOL;
        $pid = pcntl_fork();
        switch($pid){
            case -1:
                exit("Fork failed");
                break;
            case 0:
    //            echo "
    I'm the child  process: " . posix_getpid() . ' and $pid='.$pid.PHP_EOL;
    
                require __DIR__.'/../vendor/autoload.php';
                $connection = new AMQPStreamConnection('localhost', 5672, 'guest', 'guest', '/');
                $channel = $connection->channel();
                $channel->queue_declare('hello', false, false, false, false);
    
    //            echo ' [*] Waiting for messages. To exit press CTRL+C', "
    ";
    
                $callback = function ($msg) {
    //                echo " [x] Received ", $msg->body, "
    ";
                };
    
                $channel->basic_consume('hello', '', false, true, false, false, $callback);
    
                while (count($channel->callbacks)) {
                    $channel->wait();
                }
    
                $channel->close();
                $connection->close();
    
                break;
            default:
                $child[$pid] = $pid;
                //echo "I'm the parent process: " . posix_getpid() .' and $pid='.$pid .PHP_EOL;
                break;
        }
    
    }
    
    $fork_nums = 2;
    
    for($i = 0;$i < $fork_nums;$i++)
    {
        forkPro();
    }
    
    while(count($child))
    {
        if(($exit_id = pcntl_wait($status)) > 0){
    //        echo "有子进程退出,进程ID是:" . $exit_id . PHP_EOL;
    //        echo "被中断的子进程的信号值是:" . pcntl_wtermsig($status) . PHP_EOL;
            unset($child[$exit_id]);//从子进程集合中移除已经退出的子进程
        }
        if(count($child) < $fork_nums){   //当集合中的子进程数量小于一定量时,自动fork新的子进程
            forkPro();
        }
    }

          2. 编写shell脚本,这里大家有空可以自行百度一下基础教程即可,我也不是很精通,只是写一些简单的

          

    mq_count=`ps -ef|grep fork_demo.php | grep -v grep | wc -l`
    if [ $mq_count -lt 4 ]
    then
        cd /mnt/www/lmrs/public && php fork_demo.php reload
    else
        echo 1
    fi

          这里的 fork_demo.php 文件是你的php监听脚本文件,这里主要是检测你当前有多少个进程,如果不足的时候就新增等等。写完shell脚本,可以自行添加到crontab任务即可。

        

    .  

  • 相关阅读:
    Deploying an Application on X11 Platforms
    使用xenu查找web站点死链接使用方法及结果分析 Binbby 博客园
    About | Channel 9
    Amber is an implementation of the Smalltalk language that runs on top of the JavaScript runtime.
    linux下qt静态编译_自由出土文物的空间_百度空间
    A year of Qt ecosystem growth with Digia nurturing Qt Commercial
    华汇超市二层的小餐馆可当MBA案例了
    js web tools
    [转]PAC Manager: Ubuntu 上强大的 SSH 帐号管理工具,可取代 SecureCRT_Miracle_百度空间
    qq云输入法也支持五笔了,太适合我了,特别是在ubuntu下有时候输入法
  • 原文地址:https://www.cnblogs.com/hurry-up/p/15457526.html
Copyright © 2020-2023  润新知