消息中間件RabbitMQ入門到進階之簡單隊列(simple)

大綱

此套免費課程視頻,錄播到了騰訊課堂 更多請關注騰訊課堂 牧碼人
https://ke.qq.com/course/288116#tuin=5740604a
1.消息中間件概述,使用場景(日誌處理,異步,系統解耦,流量削鋒)
2.Rabbitmq3.7.2安裝,控制檯簡介,管理員添加
3.用戶vhost配置以及介紹
4.java操作簡單隊列,生產者發送消息到隊列,消費者接收消息
5.簡單隊列的缺陷,工作隊列work queues之 輪詢分發(Round-robin),以及輪詢分發現象
6.工作隊列work queues 公平分發(fair dispatch);prefetchCount = 1來限制RabbitMQ發送的消息,手動應答ack。
7.消息應答ack與消息持久化durable
8.publish/subscribe發佈訂閱模式 交換機(轉發器)匿名轉發Nameless exchange, Fanout Exchange不處理路由鍵 , Direct Exchange處理路由鍵, Topic Exchange將路由鍵和某模式進行匹配。隊列綁定交換機(Exchange) ;
9.routing路由模式
10.topic主題模式
11.Rabbitmq之消息確認機制(AMQP事務機制)txSelect(), txCommit()以及txRollback(),事務機制的缺陷
12.Rabbitmq之消息確認機制(Confirm機制串行) waitForConfirms
13.Rabbitmq之消息確認機制(Confirm機制異步) ConfirmListener deliveryTag unconfirm集合維護
14.spring集成rabbitmq-client,template 的使用
15.大數據日誌收集系統消息中間件應用
16.搜索系統DIH消息中間件應用

simple隊列

maven依賴



com.rabbitmq
amqp-client
4.0.2

    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>1.7.10</version>
    </dependency>

    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-log4j12</artifactId>
        <version>1.7.5</version>
    </dependency>

    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>1.2.17</version>
    </dependency>

    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.11</version>
    </dependency>
</dependencies>

模型

這裏寫圖片描述

P:消息的生產者
C:消息的消費者
紅色:隊列

生產者將消息發送到隊列,消費者從隊列中獲取消息。

那麼我們根據以上的模型,咱們抽取出 3個對象 生產者(用戶發送消息) 隊列(中間件):類似於容器(存儲消息) 消費者(獲取隊列中的消息)

JAVA操作 獲取MQ連接

類似於我們在操作數據庫的時候,的要獲取到連接,然後纔對數據進行操作

package com.mmr.rabbitmq.conn;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.Connection;
public class ConnectionUtils {
    public static Connection getConnection() throws IOException, TimeoutException {
        //定義連接工廠
        ConnectionFactory factory = new ConnectionFactory();
        //設置服務地址
        factory.setHost("127.0.0.1");
        //端口
        factory.setPort(5672);//amqp協議 端口 類似與mysql的3306
        //設置賬號信息,用戶名、密碼、vhost
        factory.setVirtualHost("/vhost_mmr");
        factory.setUsername("user_mmr");
        factory.setPassword("admin");
        // 通過工程獲取連接
        Connection connection = factory.newConnection();
        return connection;
    }
}

生產者發送數據到消息隊列

public class SendMQ {
    private static final String QUEUE_NAME="QUEUE_simple";
    /*
        P----->|QUEUE |
    */
    @Test
    public void sendMsg() throws Exception {
        /* 獲取一個連接 */
        Connection connection = ConnectionUtils.getConnection();

        /*從連接中創建通道*/
        Channel channel = connection.createChannel();

        //創建隊列 (聲明)  因爲我們要往隊列裏面發送消息,這是後就得知道往哪個隊列中發送,就好比在哪個管子裏面放水,
        boolean durable=false;
        boolean exclusive=false;
        boolean autoDelete=false;
        channel.queueDeclare(QUEUE_NAME, durable, exclusive, autoDelete, null);//如果這個隊列不存在,其實這句話是不需要的

        String msg="Hello  Simple QUEUE !";
         //第一個參數是exchangeName(默認情況下代理服務器端是存在一個""名字的exchange的,
         //因此如果不創建exchange的話我們可以直接將該參數設置成"",如果創建了exchange的話
         //我們需要將該參數設置成創建的exchange的名字),第二個參數是路由鍵
        channel.basicPublish("", QUEUE_NAME, null, msg.getBytes());
        System.out.println("---------send ms :"+msg);

        channel.close();
        connection.close();
    }
}

消費者消費

package com.mmr.rabbitmq.simple;

import java.io.IOException;

import com.mmr.rabbitmq.conn.ConnectionUtils;
import com.rabbitmq.client.AMQP.BasicProperties;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.Envelope;
import com.rabbitmq.client.QueueingConsumer;

public class Consumer {
    private static final String QUEUE_NAME  = "QUEUE_simple";

    public static void main(String[] args) throws Exception {

        /* 獲取一個連接 */
        Connection connection = ConnectionUtils.getConnection();
        Channel channel = connection.createChannel();

        //聲明隊列  如果能確定是哪一個隊列 這邊可以刪掉,不去掉 這裏會忽略創建
        //channel.queueDeclare(QUEUE_NAME, false, false, false, null);

        DefaultConsumer consumer = new DefaultConsumer(channel) {
            //獲取到達的消息
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, BasicProperties properties, byte[] body) throws IOException {
                String message = new String(body, "UTF-8");
                System.out.println(" [x] Received '" + message + "'");
            }
        };

        //監聽隊列
        channel.basicConsume(QUEUE_NAME, true, consumer);
    }

    @SuppressWarnings("deprecation")
    private static void oldGet(Channel channel) throws IOException, InterruptedException {
        //定義隊列的消費者
        QueueingConsumer consumer = new QueueingConsumer(channel);
        // 監聽隊列
        channel.basicConsume(QUEUE_NAME, true, consumer);
        // 獲取消息
        while (true) {
            QueueingConsumer.Delivery delivery = consumer.nextDelivery();
            String message = new String(delivery.getBody());
            System.out.println(" [x] Received '" + message + "'");
        }
    }
}

簡單隊列的不足

耦合性高 生產消費一一對應(如果有多個消費者想都消費這個消息,就不行了) 隊列名稱變更時需要同時更改

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章