4.rabbitmq--路由模式
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--路由模式的更多相关文章
- RabbitMQ路由模式
生产者 import com.rabbitmq.client.Channel; import com.rabbitmq.client.Connection; import utils.Connecti ...
- rabbitMQ的三种路由模式
rabbitMQ工作流程: 1.声明交换机 2.声明消息队列 3.绑定交换机和队列 4.生产者往交换机里发送新消息 5.交换机根据所选的模式和routingKey决定消息发往哪条消息队列 6.一个消费 ...
- RabbitMQ (六) 订阅者模式之路由模式 ( direct )
路由模式下,生产者发送消息时需要指定一个路由键(routingKey),交换机只会把消息转发给包含该路由键的队列 这里,我们改变一下声明交换机的方式. 我们通过管理后台添加一个交换机. 添加后,生产者 ...
- RabbitMQ六种队列模式-路由模式
前言 RabbitMQ六种队列模式-简单队列RabbitMQ六种队列模式-工作队列RabbitMQ六种队列模式-发布订阅RabbitMQ六种队列模式-路由模式 [本文]RabbitMQ六种队列模式-主 ...
- RabbitMQ学习第四记:路由模式(direct)
1.什么是路由模式(direct) 路由模式是在使用交换机的同时,生产者指定路由发送数据,消费者绑定路由接受数据.与发布/订阅模式不同的是,发布/订阅模式只要是绑定了交换机的队列都会收到生产者向交换机 ...
- RabbitMQ 一二事(4) - 路由模式介绍
路由模式其实和订阅模式差不多,只不过交换机的类型不同而已 路由模式可以用下图来表示,比订阅模式多了一个key,举个栗子就是根据不同的人群来订阅公众号,来收取消息 根据不同的key来获取不同的消息 最简 ...
- python使用rabbitMQ介绍四(路由模式)
一.模式介绍 路由模式,与发布-订阅模式一样,消息发送到exchange中,消费者把队列绑定到exchange上. 这种模式在exchange上添加添加了一个路由键(routing-key),生产者发 ...
- RabbitMQ路由类型
关于RabbitMQ的Exchange类型 参考地址:<RabbitMQ学习系列(四): 几种Exchange 模式> github地址:https://github.com/ChenWe ...
- 1.RabbitMq - Work 模式
RabbitMq - Work 模式 一.什么是Work模式 如果有几个消息都需要处理,且每个消息的处理时间很长,仅有一个消费者,那么当它在处理一个消息的时候,其他消息就只有等待. 等待有时候是好的, ...
- RabbitMQ工作模式
------------恢复内容开始------------ RabbitMQ基本概念: Producer:生产者(消息的提供者) Consumer:消费者(消息的使用者) Message:消息(程序 ...
随机推荐
- C++ STL 之 string
#include <iostream> #include <string> using namespace std; // 初始化 void test01() { string ...
- bash shell脚本之获取时间日期
shell中的时间日期获取 cat test5: #!/bin/bash # using the backtick character testing=`date` echo "The da ...
- 目标检测后处理之NMS(非极大值抑制算法)
1.定义: 非极大值抑制算法NMS广泛应用于目标检测算法,其目的是为了消除多余的候选框,找到最佳的物体检测位置. 2.原理: 使用深度学习模型检测出的目标都有多个框,如下图,针对每一个被检测目标,为了 ...
- linux基础4-压缩及其相关的命令
一 压缩的原理以及gzip.bzip2.tar三个命令的: Linux下文件的压缩与打包 二 zip.zipinfo.unzip: zip:压缩成.zip文件 zipinfo:列出压缩文件信息
- seaborn图形
kdeplot(核密度估计图) 核密度估计(kernel density estimation)是在概率论中用来估计未知的密度函数,属于非参数检验方法之一.通过核密度估计图可以比较直观的看出数据样本本 ...
- Linux学习笔记(三)Linux常用命令:链接命令和文件查找命令
一.链接命令 ln -s [原文件] [目标文件] (link) -s意为创建软连接 硬链接和软连接 硬链接的特点: (1)拥有相同的 i 结点和block块,可以看作是同一个文件 (2)可以通过 i ...
- 树的总结(遍历,BST,AVL原型,堆,练习题)
目录 树 一.抽象数据类型 二.二叉树的性质 三.二叉树的遍历 三.活用树的遍历 四.BST树 五.AVL树 六.BST树和AVL树练习 七.堆 树 @ 一.抽象数据类型 1.顺序存储 使用数组存储 ...
- Educational Codeforces Round 40 C. Matrix Walk( 思维)
Educational Codeforces Round 40 (Rated for Div. 2) C. Matrix Walk time limit per test 1 second memor ...
- Windows&Appium&Java&Python自动化测试-配置开发环境
摘要 本篇博文,主要介绍借助Appium做移动端自动化测试的开发环境搭建,包括Java和Python Java环境:Appium+Maven+Idea+TestNG+Reportng Python环境 ...
- python 中 open与with open 的区别
读写文件是最常见的IO操作.Python内置了读写文件的函数,用法和C是兼容的. 读写文件前,我们先必须了解一下,在磁盘上读写文件的功能都是由操作系统提供的,现代操作系统不允许普通的程序直接操作磁盘, ...