前言
在上一個教程中,我們創建了一個工作隊列。工作隊列背後的假設是,每個任務都恰好交付給一個工人。在這一部分中,我們將做一些完全不同的事情-我們將消息傳達給多個消費者。這種模式稱爲“發佈/訂閱”。
爲了說明這種模式,我們將構建一個簡單的日誌記錄系統。它由兩個程序組成-第一個程序將發出日誌消息,第二個程序將接收並打印它們。
在我們的日誌系統中,接收器程序的每個運行副本都將獲得消息。這樣,我們將能夠運行一個接收器並將日誌定向到磁盤。同時我們將能夠運行另一個接收器並在屏幕上查看日誌。
本質上,已發佈的日誌消息將被廣播到所有接收者。
RabbitMQ消息傳遞模型中的核心思想是生產者從不將任何消息直接發送到隊列。實際上,生產者經常甚至根本不知道是否將消息傳遞到任何隊列。
相反,生產者只能將消息發送到交換機。交流是一件非常簡單的事情。一方面,它接收來自生產者的消息,另一方面,將它們推入隊列。交易所必須確切知道如何處理收到的消息。是否應將其附加到特定隊列?是否應該將其附加到許多隊列中?還是應該丟棄它。規則由交換類型定義 。
有幾種交換類型可用:direct,topic,headers和fanout。我們討論最後一種-fanout。扇型理解起來很簡單,它只是將它接收到消息廣播到它知道的所有隊列當中。
一、引入RabbitMQ的開發包
<dependency>
<groupId>com.rabbitmq</groupId>
<artifactId>amqp-client</artifactId>
<version>3.6.6</version>
</dependency>
二、連接工具
package com.example.demo.util;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
/**
* 消息隊列連接工具
*
*/
public class MQConnectionUtils {
public static Connection connection() throws IOException, TimeoutException{
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("127.0.0.1");
factory.setUsername("guest");
factory.setPassword("guest");
factory.setPort(5672);
return factory.newConnection();
}
}
三、生產者
package com.example.demo.produce;
import com.example.demo.util.MQConnectionUtils;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
/**
* 訂閱模式 - 生產者
*
*/
public class SubscribeProduce {
private static final String EXCHANGE_NAME = "my_fanout_subscribe";
public static void main(String[] args) throws IOException, TimeoutException {
Connection connection = MQConnectionUtils.connection();
Channel channel = connection.createChannel();
channel.exchangeDeclare(EXCHANGE_NAME, "fanout");
String msg = "hello,我是訂閱模式-生產者";
channel.basicPublish(EXCHANGE_NAME, "", null, msg.getBytes());
System.out.println("生產者投遞消息===>" + msg);
channel.close();
connection.close();
}
}
四、消費者
package com.example.demo.consume;
import com.example.demo.util.MQConnectionUtils;
import com.rabbitmq.client.*;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.concurrent.TimeoutException;
/**
* 訂閱模式 - 消費者1(短信)
*
*/
public class SubscribeConsume1 {
private static final String EXCHANGE_NAME = "my_exchange_fanout";
private static final String SUBSCRIBE_QUEUE_SMS = "subscribe_queue_sms";
public static void main(String[] args) throws IOException, TimeoutException {
Connection connection = MQConnectionUtils.connection();
Channel channel = connection.createChannel();
channel.queueDeclare(SUBSCRIBE_QUEUE_SMS, false, false, false, null);
channel.queueBind(SUBSCRIBE_QUEUE_SMS, EXCHANGE_NAME, "");
DefaultConsumer defaultConsumer = new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body)
throws IOException {
String msg = new String(body,"UTF-8");
System.out.println("短信消費者獲取的消息:<" + msg + ">");
}
};
channel.basicConsume(SUBSCRIBE_QUEUE_SMS, true, defaultConsumer);
}
}
package com.example.demo.consume;
import com.example.demo.util.MQConnectionUtils;
import com.rabbitmq.client.*;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.concurrent.TimeoutException;
/**
* 訂閱模式-消費者2(郵箱)
*
* @date: 2019-12-09 22:14:11
*/
public class SubscribeConsume2 {
private static final String EXCHANGE_NAME = "my_exchange_fanout";
private static final String SUBSCRIBE_QUEUE_EMAIL = "subscribe_queue_email";
public static void main(String[] args) throws IOException, TimeoutException {
Connection connection = MQConnectionUtils.connection();
Channel channel = connection.createChannel();
channel.queueDeclare(SUBSCRIBE_QUEUE_EMAIL, false, false, false, null);
channel.queueBind(SUBSCRIBE_QUEUE_EMAIL, EXCHANGE_NAME, "");
// 監聽隊列
DefaultConsumer defaultConsumer = new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws UnsupportedEncodingException {
String msg = new String(body, "utf-8");
System.out.println("郵件消費者獲取到的消息:<" + msg + ">");
}
};
channel.basicConsume(SUBSCRIBE_QUEUE_EMAIL, true, defaultConsumer);
}
}
五、啓動服務