rabbitmq--路由模式

想象之前的订阅发布模式: 一个生产者,多个消费者,每一个消费者都有自己的一个队列,生产者没有将消息直接发送到队列,而是发送到了交换机,每个队列绑定交换机,生产者发送的消息经过交换机,到达队列,实现一个消息被多个消费者获取的目的。

需要注意的是,如果将消息发送到一个没有队列绑定的exchange上面,那么该消息将会丢失,这是因为在rabbitMQ中exchange不具备存储消息的能力,只有队列具备存储消息的能力。

但是如果想象下这样的一个场景:生产者有新增商品,修改商品,删除商品的消息,消费者包含前台系统和搜索系统,要求前台系统接收修改和删除商品的消息,搜索系统接收新增商品、修改商品和删除商品的消息。所以使用这种订阅模式实现商品数据的同步并不合理。因此我们介绍下一种模式:路由模式。

这种模式添加了一个路由键,生产者发布消息的时候添加路由键,消费者绑定队列到交换机时添加键值,这样就可以接收到需要接收的消息。

 生产者:

 package com.maozw.mq.routing;

 import com.maozw.mq.config.RabbitConfig;
import com.rabbitmq.client.Channel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.rabbit.connection.Connection;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import java.io.IOException;
import java.util.concurrent.TimeoutException; import static org.apache.log4j.varia.ExternallyRolledFileAppender.OK; /**
* work 模式
* 两种分发: 轮询分发 + 公平分发
* 轮询分发:消费端:自动确认消息;boolean autoAck = true;
* 公平分发: 消费端:手动确认消息 boolean autoAck = false; channel.basicAck(envelope.getDeliveryTag(),false);
*
* @author MAOZW
* @Description: ${todo}
* @date 2018/11/26 15:06
*/
@RestController
@RequestMapping("/routing")
public class RoutingProducer {
private static final Logger LOGGER = LoggerFactory.getLogger(RoutingProducer.class);
@Autowired
RabbitConfig rabbitConfig; @RequestMapping("/send")
public String send() throws IOException, TimeoutException {
Connection connection = null;
Channel channel= null;
try {
ConnectionFactory connectionFactory = rabbitConfig.connectionFactory();
connection = connectionFactory.createConnection();
channel = connection.createChannel(false); /**
* 申明交换机 以及type
*/
channel.exchangeDeclare(RabbitConfig.EXCHANGE_ROUTE,"direct"); /**
* 发送消息
* 每个消费者 发送确认消息之前,消息队列不会发送下一个消息给消费者,一次只处理一个消息
* 自动模式无需设置下面设置
*/
int prefetchCount = 1;
channel.basicQos(prefetchCount); String Hello = ">>>> Hello EXCHANGE_ROUTE <<<<";
for (int i = 0; i < 5; i++) {
String message = Hello + i;
if (i == 3){
channel.basicPublish(RabbitConfig.EXCHANGE_ROUTE, RabbitConfig.ROUTINGKEY_A, null, message.getBytes());
}else{
channel.basicPublish(RabbitConfig.EXCHANGE_ROUTE, RabbitConfig.ROUTINGKEY_B, null, message.getBytes());
}
LOGGER.info("生产消息: " + message);
}
return "OK";
}catch (Exception e) { } finally {
connection.close();
channel.close();
return OK;
}
}
}

消费者1 

 package com.maozw.mq.routing;

 import com.maozw.mq.config.RabbitConfig;
import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.Envelope;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.rabbit.connection.Connection;
import org.springframework.amqp.rabbit.connection.ConnectionFactory; import java.io.IOException; /**
* @author MAOZW
* @Description: ${todo}
* @date 2018/11/26 15:06
*/ public class RoutingConsumer {
private static final Logger LOGGER = LoggerFactory.getLogger(RoutingConsumer.class); public static void main(String[] args) throws IOException {
ConnectionFactory connectionFactory = RabbitConfig.getConnectionFactory();
Connection connection = connectionFactory.createConnection();
Channel channel = connection.createChannel(false);
/**
* 创建队列申明
*/
boolean durable = true;
channel.queueDeclare(RabbitConfig.QUEUE_ROUTE, durable, false, false, null);
/**
* 绑定队列到交换机
*/
channel.queueBind(RabbitConfig.QUEUE_ROUTE, RabbitConfig.EXCHANGE_ROUTE,RabbitConfig.ROUTINGKEY_A); /**
* 改变分发规则
*/
channel.basicQos(1);
DefaultConsumer consumer = new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
super.handleDelivery(consumerTag, envelope, properties, body);
System.out.println("[1] 接口数据 : " + new String(body, "utf-8"));
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println("[1] done!");
//消息应答:手动回执,手动确认消息
channel.basicAck(envelope.getDeliveryTag(),false);
}
}
};
//监听队列
/**
* autoAck 消息应答
* 默认轮询分发打开:true :这种模式一旦rabbitmq将消息发送给消费者,就会从内存中删除该消息,不关心客户端是否消费正常。
* 使用公平分发需要关闭autoAck:false 需要手动发送回执
*/
boolean autoAck = false;
channel.basicConsume(RabbitConfig.QUEUE_ROUTE,autoAck, consumer);
} }
 package com.maozw.mq.routing;

 import com.maozw.mq.config.RabbitConfig;
import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.Envelope;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.rabbit.connection.Connection;
import org.springframework.amqp.rabbit.connection.ConnectionFactory; import java.io.IOException; /**
* @author MAOZW
* @Description: ${todo}
* @date 2018/11/26 15:06
*/ public class RoutingConsumer2 {
private static final Logger LOGGER = LoggerFactory.getLogger(RoutingConsumer2.class); public static void main(String[] args) throws IOException {
ConnectionFactory connectionFactory = RabbitConfig.getConnectionFactory();
Connection connection = connectionFactory.createConnection();
Channel channel = connection.createChannel(false);
/**
* 创建队列申明
*/
boolean durable = true;
channel.queueDeclare(RabbitConfig.QUEUE_ROUTE2, durable, false, false, null);
/**
* 绑定队列到交换机
*/
channel.queueBind(RabbitConfig.QUEUE_ROUTE2, RabbitConfig.EXCHANGE_ROUTE,RabbitConfig.ROUTINGKEY_B); /**
* 改变分发规则
*/
channel.basicQos(1);
DefaultConsumer consumer = new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
super.handleDelivery(consumerTag, envelope, properties, body);
System.out.println("[2] 接口数据 : " + new String(body, "utf-8"));
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println("[2] done!");
//消息应答:手动回执,手动确认消息
channel.basicAck(envelope.getDeliveryTag(),false);
}
}
};
//监听队列
/**
* autoAck 消息应答
* 默认轮询分发打开:true :这种模式一旦rabbitmq将消息发送给消费者,就会从内存中删除该消息,不关心客户端是否消费正常。
* 使用公平分发需要关闭autoAck:false 需要手动发送回执
*/
boolean autoAck = false;
channel.basicConsume(RabbitConfig.QUEUE_ROUTE2,autoAck, consumer);
}
}

4.rabbitmq--路由模式的更多相关文章

  1. RabbitMQ路由模式

    生产者 import com.rabbitmq.client.Channel; import com.rabbitmq.client.Connection; import utils.Connecti ...

  2. rabbitMQ的三种路由模式

    rabbitMQ工作流程: 1.声明交换机 2.声明消息队列 3.绑定交换机和队列 4.生产者往交换机里发送新消息 5.交换机根据所选的模式和routingKey决定消息发往哪条消息队列 6.一个消费 ...

  3. RabbitMQ (六) 订阅者模式之路由模式 ( direct )

    路由模式下,生产者发送消息时需要指定一个路由键(routingKey),交换机只会把消息转发给包含该路由键的队列 这里,我们改变一下声明交换机的方式. 我们通过管理后台添加一个交换机. 添加后,生产者 ...

  4. RabbitMQ六种队列模式-路由模式

    前言 RabbitMQ六种队列模式-简单队列RabbitMQ六种队列模式-工作队列RabbitMQ六种队列模式-发布订阅RabbitMQ六种队列模式-路由模式 [本文]RabbitMQ六种队列模式-主 ...

  5. RabbitMQ学习第四记:路由模式(direct)

    1.什么是路由模式(direct) 路由模式是在使用交换机的同时,生产者指定路由发送数据,消费者绑定路由接受数据.与发布/订阅模式不同的是,发布/订阅模式只要是绑定了交换机的队列都会收到生产者向交换机 ...

  6. RabbitMQ 一二事(4) - 路由模式介绍

    路由模式其实和订阅模式差不多,只不过交换机的类型不同而已 路由模式可以用下图来表示,比订阅模式多了一个key,举个栗子就是根据不同的人群来订阅公众号,来收取消息 根据不同的key来获取不同的消息 最简 ...

  7. python使用rabbitMQ介绍四(路由模式)

    一.模式介绍 路由模式,与发布-订阅模式一样,消息发送到exchange中,消费者把队列绑定到exchange上. 这种模式在exchange上添加添加了一个路由键(routing-key),生产者发 ...

  8. RabbitMQ路由类型

    关于RabbitMQ的Exchange类型 参考地址:<RabbitMQ学习系列(四): 几种Exchange 模式> github地址:https://github.com/ChenWe ...

  9. 1.RabbitMq - Work 模式

    RabbitMq - Work 模式 一.什么是Work模式 如果有几个消息都需要处理,且每个消息的处理时间很长,仅有一个消费者,那么当它在处理一个消息的时候,其他消息就只有等待. 等待有时候是好的, ...

  10. RabbitMQ工作模式

    ------------恢复内容开始------------ RabbitMQ基本概念: Producer:生产者(消息的提供者) Consumer:消费者(消息的使用者) Message:消息(程序 ...

随机推荐

  1. SpringBoot-JPA入门

    SpringBoot-JPA入门 JPA就是Spring集成了hibernate感觉. 注解,方法仓库(顾名思义的方法,封装好了,还有自定义的方法). 案例: spring: datasource: ...

  2. SparkSQL读取HBase数据

    这里的SparkSQL是指整合了Hive的spark-sql cli(关于SparkSQL和Hive的整合,见文章后面的参考阅读). 本质上就是通过Hive访问HBase表,具体就是通过hive-hb ...

  3. Oracle 调试存储过程

    调试过程对找到一个存过的bug或错误是非常重要的,Oracle作为一款强大的商业数据库,其上面的存过少则10几行,多则上千行,免不了bug的存在,存过上千行的话,找bug也很费力,通过调试可以大大减轻 ...

  4. LCD1602 液晶

    它是一种专门用来显示字母.数字.符号的点阵型液晶模块 它是由若干个5x7或者5x10的点阵字符位组成 引脚 时序 操作步骤 初始化 写命令(RS=L)设置显示坐标 写数据(RS=H) 指令 清屏: 指 ...

  5. Webstorm2017.3.3软件的安装使用

    下载 ▶进入jetbrains的官方网站点击download,即下载开始.官方网站链接:http://www.jetbrains.com/webstorm/ 安装 ▶双击刚下载完成的.exe文件开始进 ...

  6. 【转】Delphi货币类型转中文大写金额

    unit TU2.Helper.Currency; interface ): string; ): string; implementation uses System.SysUtils, Syste ...

  7. Azkaban无法启动错误Error: Could not find or load main class 12321

    1 错误日志 Using Hadoop from /mnt/software/hadoop-2.6.0-cdh5.16.1 bin/internal/../.. /mnt/software/jdk1. ...

  8. 如何制作 linux 系统 U盘启动盘

    1.制作linux 系统的U盘启动盘,需要选择ISO 模式!给大家推荐几个制作相关软件以及相关制作过程(点击相应名字即可进入到网站):UltraISO.rufus.老毛桃.大白菜. UltraISO ...

  9. Prometheus 监控 Redis 集群的正确姿势

    Prometheus 监控Redis的正确姿势(redis集群) Prometheus 监控 Redis cluster,其实套路都是一样的,使用 exporter. exporter 负责采集指标, ...

  10. Java工程师面试题集锦

    即将踏上找工作的征途,参考网上面试题库准备一波面试题,希望能找到理想中的工作,愿一切顺利. 一.Java基础 1.String类为什么是final的. 2.HashMap的源码,实现原理,底层结构. ...