RabbitMQ自學入門

// 連接RabbitMQ 簡單工具類

public static Connection getConnection() throws Exception {
        //1. 定義一個連接工廠
        ConnectionFactory factory = new ConnectionFactory();
        //2. 獲取服務地址
        factory.setHost("127.0.0.1");
        //3. AMQP 5672
        factory.setPort(5672);
        //4. vhost
        factory.setVirtualHost("/test");
        //5. 用戶名
        factory.setUsername("test");
        //6. 密碼
        factory.setPassword("test");
        return factory.newConnection();
    }

 

// 獲取連接,生成通道

Connection connection = ConnectionUtils.getConnection();

Channel channel = connection.createChannel();

1)simple - 簡單隊列

涉及3個對象: 生產者  隊列 RabbitMQ  消費者

生產者:

    // 申明隊列

    channel.queueDeclare(QUEUE_NAME,false,false,false,null);

    // 推送信息

    channel.basicPublish("",QUEUE_NAME,null,msg.getBytes());

消費者:

    // 申明隊列

    channel.queueDeclare(QUEUE_NAME,false,false,false,null);
 
     DefaultConsumer consumer = new DefaultConsumer(channel) {
            //獲取到達的消息
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                String msg = new String(body, "utf-8");

                // 消費消息
                System.out.println("new api recv: " + msg);
            }
        };
 
        //4. 監聽隊列
        channel.basicConsume(QUEUE_NAME,true,consumer);

缺點:耦合性高,生產者一 一對應消費者。

 

2)work queues - 工作隊列

channel.basicQos(1); //保證每次只分發一個

boolean autoAck = true;

channel.basicConsume(QUEUE_NAME,autoAck,consumer);

autoAck true 代表自動應答,

false代表需要如下手動應答:

channel.basicAck(envelope.getDeliveryTag(),false);

輪詢分發:自動應答,任務消息總是均勻分配

公平分發:手動應答,能者多勞

 

3)消息持久化

Boolean durable = true;// 持久化,注意在已存在的隊列上修改是不行的,可以刪除原有隊列或重新生成隊列。

channel.queueDeclare(QUEUE_NAME,durable ,false,false,null);

 

4)訂閱模式 publish/subscribe

  • 一個生產者,多個消費者
  • 每一個消費者都有自己的隊列
  • 生產者沒有直接把消息發送到隊列 而是發送到了交換機 轉發器(exchange)
  • 每個隊列都要綁定到交換機上,
  • 生產者發送的消息 經過交換機 達到隊列 就能實現一個消息被多個消費者消費

生產者:

channel.exchangeDeclare(EXCHANGE_NAME,"fanout"); // 聲明交換機,"fanout"爲分發

消費者:

channel.queueBind(QUEUE_NAME,EXCHANGE_NAME,"");//綁定隊列到交換機轉發器

 

5)Exchange(交換機 轉發器)

一方面是接收生產者的消息,另一方面是向隊列推送消息。

匿名轉發 ""

fanout(不處理路由鍵)

direct (處理路由器)

 

6)路由模式

生產者:

channel.exchangeDeclare(EXCHANGE_NAME,"direct"); // 聲明交換機

String routingKey = "info"; // error、warn..  綁定路由

channel.basicPublish(EXCHANGE_NAME,routingKey ,null,msg.getBytes());

消費者:

channel.queueBind(QUEUE_NAME,EXCHANGE_NAME,"info");// 消費者綁定到路由

 

7)事務機制

txSelect  txCommit  txRollback

txSelect:用戶將當前 channel 設置成 transaction 模式

txCommit  :用於提交事務;

txRollback:回滾事務。

這種模式很耗時,採用這種方式,降低了 RabbitMQ 的消息吞吐量
 

8)Conform 模式

生產者端 conform 模式的實現原理:

生產者將信道設置成 conform 模式,一旦信道進入 conform 模式,所有在該信道上面發佈的消息都會被指派一個唯一的 ID(從 1 開始),一旦消息被投遞到所有匹配的隊列之後,broker 就會發送一個確認給生產者(包含消息的唯一ID),這就使得生產者知道消息已經到達目的隊列了,如果消息和隊列是持久化的,那麼確認消息會將消息寫入磁盤之後發出,broker 也可以設置 basic.ack 的 multiple 域,表示到這個序列號之前的所有消息都已經得到了處理。

Conform 模式最大的好處就是他是異步。

開啓 conform 模式    Channel.conformSelect()

編程模式:

①普通 發一條 waitForConfirms()

②批量的 發一批 channel.waitForConfirmsOrDie(); //直到所有信息都發布,只要有一個未確認就會IOException

③異步 conform 模式:提供一個 回調方法
 

異步模式:

channel 對象提供的 ConfirmListener() 回調方法只包含 deliveryTag (當前 channel 發出的消息序列),我們需要自己爲每一個 Channel 維護一個 unconfirm 的消息序號集合,每 publish 一條數據,集合中元素加 1 ,每回調一次 handleAck 方法,unconfirm 集合刪掉相應的一條(multiple = false)或多條(multiple = true)記錄。從程序運行效率上看,這個 unconfirm 集合最好採用有序集合 SortedSed 存儲結構。

例如:

SortedSet<Long> confirmSet = Collections.synchronizedSortedSet(new TreeSet<Long>());
channel.confirmSelect();
channel.addConfirmListener(new ConfirmListener() {
       public void handleAck(long deliveryTag, boolean multiple) throws IOException {
            if (multiple) {
                  confirmSet.headSet(deliveryTag + 1L).clear();
              } else {
                    confirmSet.remove(deliveryTag);
              }
       }
       public void handleNack(long deliveryTag, boolean multiple) throws IOException {
             if (multiple) {
                 confirmSet.headSet(deliveryTag + 1L).clear();
              } else {
                  confirmSet.remove(deliveryTag);
              }
        }
});

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