RabbitMQ

  1. 是什麼?
    1. 消息中間件
    2. RabbitMQ是一個開源的AMQP實現,服務器端用Erlang語言編寫
    3. 官網:https://www.rabbitmq.com/
       
  2. 幹什麼?
    1. 案例:公衆號推送通知,發送消息到消息中間件服務器,手機微信裏的消息中間件客戶端,就會自動去把消息獲取出來顯示。
       
  3. 怎麼用?
    1. Windows
          1.下載erlang(RabbitMQ依賴erlang環境) https://www.erlang.org/downloads
              運行EXE安裝
          2.與java的jdk一樣配置環境變量,只需配置PATH,增加一個erlang安裝路徑
          3.下載rabbit http://dl.bintray.com/rabbitmq/all/rabbitmq-server/
          安裝
          4.在安裝目錄的sbin下打開cmd 輸入命令rabbitmq-plugins enable rabbitmq_management安裝可視化插件
          5.瀏覽器輸入:http://127.0.0.1:15672 進行查看,出現登錄界面即成功,賬號密碼:guest
    2. Linux
      1. 安裝之前要裝一些必要的庫:
        sudo yum install build-essential
        sudo yum install libncurses5-dev
           No package libncurses5-dev available. 如果安裝時提示無工作可做,可以終止安裝了
        sudo yum install libssl-dev
        sudo yum install m4
        sudo yum install unixodbc unixodbc-dev
        sudo yum install freeglut3-dev libwxgtk2.8-dev
        sudo yum install xsltproc
        sudo yum install fop
        sudo yum t install tk8.5
         
      2. 執行安裝依賴環境:
        sudo yum install erlang
        查看版本
        erl
         
      3. 安裝RabbitMQ:
        sudo yum install rabbitmq-server
        查看狀態
        service rabbitmq-server status
        安裝可視化插件
        sudo rabbitmq-plugins enable rabbitmq_management
        sudo chkconfig rabbitmq-server on  # 添加開機啓動RabbitMQ服務
      4. sudo /sbin/service rabbitmq-server start # 啓動服務
      5. sudo /sbin/service rabbitmq-server status  # 查看服務狀態
      6. sudo /sbin/service rabbitmq-server stop   # 停止服務
        打開端口
        /sbin/iptables -I INPUT -p tcp --dport 5672 -j ACCEPT  
      7. /sbin/iptables -I INPUT -p tcp --dport 15672 -j ACCEPT  
  4. 模式
    1. Fanout(廣播模式:一對多)
    2. Direct(指定隊列,點對點)
    3. Topic(訂閱模式,多對多,匹配模式)
    4. Header()
  5. 怎麼實現
    1. Fanout模式(廣播模式,一對多)
           1.發送者和消費者都需要聲明工廠並指定服務地址,啓動連接,創建通道
               //創建連接工廠
              ConnectionFactory factory = new ConnectionFactory();
              //設置RabbitMQ相關信息-服務地址
              factory.setHost("localhost");
              //連接
              Connection connection = factory.newConnection();
              //創建一個通道
              Channel channel = connection.createChannel();
              //發送者聲明交換機,以及消息類型
              channel.exchangeDeclare("fanout_exchange", "fanout");
      1. exchangeDeclare方法參數:
            參數一String exchange 交換器名稱
            參數二String type :交換器類型 "direct", "fanout", "topic"
            參數三Boolean durable:是否持久化,設爲true可以將交換機存盤
            參數四Boolean autoDelete:是否自動刪除(一般不設置)
      2. 生產者把消息交給消息隊列
        channel.basicPublish("fanout_exchange", "", null, message.getBytes("UTF-8"));
        1. basicPublish方法參數:
          參數一String exchange:交換器名稱
          參數二String routingKey:路由關鍵字
          參數三BasicProperties props:消息的基本屬性,例如路由頭等
          參數四byte[] body:消息體
      3. 關閉通道和連接
        channel.close();
        connection.close();
      4. 接收者 第一步與i相同
      5. 交換機中存儲的隊列需要聲明一個零時隊列
        //獲取一個臨時隊列
        String queueName = channel.queueDeclare().getQueue();
        //隊列與交換機綁定(參數爲:隊列名稱;交換機名稱;routingKey忽略)
        channel.queueBind(queueName, "fanout_exchange","");
        通過監聽,交換機中有消息則取出來
        // 監聽那個頻道的消息,如果頻道中有消息,就會執行回調函數handleDelivery
        Consumer consumer = new DefaultConsumer(channel) {
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope,
                                       AMQP.BasicProperties properties, byte[] body)
                    throws IOException {
                String message = new String(body, "UTF-8");
                System.out.println(name + " 接收到消息 '" + message + "'");
            }
        };
        //自動回覆隊列 RabbitMQ中的消息確認機制,表示已經取了該條消息了
        channel.basicConsume(queueName, true, consumer);
    2. Direct(指定隊列,點對點)
      1. 發送者,直接發送消息,給消息隊列,並指定路由關鍵字
        //創建連接工廠
        ConnectionFactory factory = new ConnectionFactory();
        //設置RabbitMQ相關信息-服務地址
        factory.setHost("localhost");
        //連接
        Connection connection = factory.newConnection();
        //創建一個通道
        Channel channel = connection.createChannel();
        1. //發送者,發送消息到隊列中,參數與a)ii.1相同
        2. channel.basicPublish("","direct_queue", null, message.getBytes("UTF-8"));
      2. 接收者
        //創建連接工廠
        ConnectionFactory factory = new ConnectionFactory();
        //設置RabbitMQ相關信息-服務地址
        factory.setHost("localhost");
        //連接
        Connection connection = factory.newConnection();
        //創建一個通道
        Channel channel = connection.createChannel();
        //聲明要關注的隊列
        channel.queueDeclare("direct_queue", false, false, true, null);
        1. queueDeclare方法參數:
          參數一String queue:隊列名稱
          參數二Boolean durable:是否持久化
          參數三 Boolean exclusive:是否在關閉時刪除該隊列,是否是私有的
          參數四 Boolean autoDelete:是否自動刪除
          參數五Map arguments:更多明細設置
        2. 剩下的取出消息,關閉連接、通道與a)vi 相同
    3. Topic(訂閱模式,多對多,匹配模式)
      1. 發送者
        //創建連接工廠
        ConnectionFactory factory = new ConnectionFactory();
        //設置RabbitMQ相關信息-服務地址
        factory.setHost("localhost");
        //創建一個新的連接
        Connection connection = factory.newConnection();
        //創建一個通道
        Channel channel = connection.createChannel();
        //聲明交換機,參數與a)1 相同
        channel.exchangeDeclare(EXCHANGE_NAME, "topic");
        //創建路由
        String[] routing_keys = new String[] { "usa.news", "usa.weather",
                "europe.news", "europe.weather" };
        //創建消息
        String[] messages = new String[] { "美國新聞", "美國天氣",
                "歐洲新聞", "歐洲天氣" };
        //把消息交給隊列,給上不同的路由,參數與a)i1相同
        for (int i = 0; i < routing_keys.length; i++) {
            String routingKey = routing_keys[i];
            String message = messages[i];
            channel.basicPublish(EXCHANGE_NAME, routingKey, null, message
                    .getBytes());
        }
      2. 接收者
        // 創建連接工廠
        ConnectionFactory factory = new ConnectionFactory();
        //設置RabbitMQ地址
        factory.setHost("localhost");
        //創建一個新的連接
        Connection connection = factory.newConnection();
        //創建一個通道
        Channel channel = connection.createChannel();
        //交換機聲明(參數爲:交換機名稱;交換機類型)
        channel.exchangeDeclare(EXCHANGE_NAME,"topic");
        //獲取一個臨時隊列
        String queueName = channel.queueDeclare().getQueue();、
        //根據模糊路由接受後綴爲news的路由消息
        channel.queueBind(queueName, EXCHANGE_NAME, "*.news");
        1. queueBind方法參數:
          參數一String queue隊列名稱
          參數二String exchange交換器名稱
          參數三String routingKey路由key
        2. 剩下的取出消息,關閉連接、通道與a)vi 相同
  6. 爲什麼用?
    1. 消息中間件常見有
      1. RocketMQ (阿里系下開源的一款分佈式、隊列模型的消息中間件)
        1. 產品新文檔缺乏
        2. 部分阿里產品未開源
        3. 未在覈心實現JMS等接口
      2. RabbitMQ(Erlang編寫的一個開源的消息隊列,支持很多的協議)
        1. Erlang語言難度大
        2. 集羣不支持動態擴展
      3. ActiveMQ(Apache下的一個子項目)
        1. 目前核心放在6.0產品Apollo上對於之前的維護較少
        2. 不適合上千隊列的使用
      4. Redis (本身支持MQ功能,所以完全可以當做一個輕量級的隊列服務)
        1. 重心更偏向存儲
      5. Kafka(Apache下的一個子項目,使用scala實現的一個高性能分佈式Publish/Subscribe消息隊列系統)
      6. ZeroMQ(號稱最快的消息隊列系統,專門爲高吞吐量/低延遲的場景開發,在金融界的應用中經常使用,偏重於實時數據通信場景)
      7. 綜合:
        1. 按照目前網絡上的資料,RabbitMQ activeM ZeroMQ 三者中,綜合來看,RabbitMQ 是首選
        2. ZeroMq 不支持,ActiveMq RabbitMq 都支持持久化消息
        3. 可靠性、靈活的路由、集羣、事務、高可用的隊列、消息排序、問題追蹤、可視化管理工具、插件RabbitMq / Kafka 最好,ActiveMq 次之,ZeroMq 最差
        4. 併發RabbitMQ 最高erlang 語言天生具備高併發高可用
  7. ​​​​​​訂閱模式​發送者
    接收者
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章