RabbitMQ 六种基本队列模式 ----- 消息订阅(Publish/Subscribe)
我们将向多个消费者传递一条信息。这种模式称为“发布/订阅”
**在之前的文章 P 和 C 已经很清楚是什么意思了,这里面的X代表的是交换机(Exchange)。交换机只负责转发消息,不具有存储消息的能力,因此如果没有队列与交换机绑定,或者没有符合规则的队列,那么消息就会丢失**
交换机的类型
- Fanout: 广播,发送到每个与交换机绑定的队列
- Direct: 定向
- Topic: 通配符
- Headers: 参数匹配
使用 java 来实现简单的 Publish/Subscribe
-
导入 Maven 坐标
<!-- https://mvnrepository.com/artifact/com.rabbitmq/amqp-client --> <dependency> <groupId>com.rabbitmq</groupId> <artifactId>amqp-client</artifactId> <version>5.9.0</version> </dependency> <!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-simple --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-simple</artifactId> <version>1.7.25</version> <!-- <scope>test</scope>--> </dependency>
-
编写 Publish 端代码
public static void main(String[] args) { final String EXCHANGE_NAME = "logs"; try { ConnectionFactory factory = new ConnectionFactory(); // 设置参数 factory.setHost("192.168.3.64"); factory.setPort(5672); factory.setVirtualHost("/default_virtual_host"); factory.setUsername("admin"); factory.setPassword("admin"); Connection connection = factory.newConnection(); Channel channel = connection.createChannel(); // 创建交换机 channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.FANOUT, true, false, false, null); // 创建队列 channel.queueDeclare("log_fanout_queue1", false, false, false, null); channel.queueDeclare("log_fanout_queue2", false, false, false, null); // 绑定队列 channel.queueBind("log_fanout_queue1", EXCHANGE_NAME, ""); channel.queueBind("log_fanout_queue2", EXCHANGE_NAME, ""); // 发送消息 String message = "[日志][支付信息][订单号:" + new Date().getTime() +"][支付ID:10]"; channel.basicPublish(EXCHANGE_NAME, "", null, message.getBytes(StandardCharsets.UTF_8)); // 释放资源 channel.close(); connection.close(); } catch (IOException | TimeoutException e) { e.fillInStackTrace(); } }
-
编写第一个 Subscribe 端代码
public static void main(String[] args) { final String EXCHANGE_NAME = "logs"; try { ConnectionFactory factory = new ConnectionFactory(); // 设置参数 factory.setHost("192.168.3.64"); factory.setPort(5672); factory.setVirtualHost("/default_virtual_host"); factory.setUsername("admin"); factory.setPassword("admin"); Connection connection = factory.newConnection(); Channel channel = connection.createChannel(); channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.FANOUT, true, false, false, null); String queue1Name = "log_fanout_queue1"; // channel.queueBind(queue1Name, EXCHANGE_NAME, ""); DeliverCallback deliverCallback = (consumerTag, delivery) -> { String message = new String(delivery.getBody(), StandardCharsets.UTF_8); System.out.println(" [x] Received '" + message + "'"); }; channel.basicConsume(queue1Name, true, deliverCallback, consumerTag -> { }); } catch (IOException e) { e.printStackTrace(); } catch (TimeoutException e) { e.printStackTrace(); } }
-
编写第二个 Subscribe 端代码
public static void main(String[] args) { final String EXCHANGE_NAME = "logs"; try { ConnectionFactory factory = new ConnectionFactory(); // 设置参数 factory.setHost("192.168.3.64"); factory.setPort(5672); factory.setVirtualHost("/default_virtual_host"); factory.setUsername("admin"); factory.setPassword("admin"); Connection connection = factory.newConnection(); Channel channel = connection.createChannel(); channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.FANOUT, true, false, false, null); String queue2Name = "log_fanout_queue2"; // channel.queueBind(queue2Name, EXCHANGE_NAME, ""); DeliverCallback deliverCallback = (consumerTag, delivery) -> { String message = new String(delivery.getBody(), StandardCharsets.UTF_8); System.out.println(" [x] Received '" + message + "'"); }; channel.basicConsume(queue2Name, true, deliverCallback, consumerTag -> { }); } catch (IOException e) { e.printStackTrace(); } catch (TimeoutException e) { e.printStackTrace(); } }
-
启动消费者和生产者
-
消息队列展示
-
消费者接收到的消息
-
欢迎前往我的个人博客 www.runbrick.com,博客园同步更新。