RabbitMq系列(一):服务器搭建
RabbitMq系列(二):最简单的例子
RabbitMq系列(三):工作队列
RabbitMq系列(四):消息确认和持久性
RabbitMq系列(五):公平派遣
RabbitMq系列(六):交换类型以及例子
RabbitMq系列(七):直接交换Direct exchange
RabbitMq系列(八):扇出交换Fanout Exchange
RabbitMq系列(九):主题交换Topic Exchange
前言
实际演示
演示1
演示2
直接交换是RabbitMq主要的四种交换类型之一,其主要是针对单对单的单路由消息通信,类似于单聊。
直接交换依赖于路由键,我们可以使用 空字符串 和 自定义路由键+交换机类型 这两种方式来快速的创建我们需要的单路由通信机制。
直接交换没有通配符的说法和应用,所以其比较规则类型于 生产者routeKey == 消费者routeKey 这样的比较方式。当消息到达交换机过后,交换机将消息带来的 routing-key( 这里就是生产者定义的 routingKey ) 与 队列绑定的 binding-key( 这里就是消费者定义的 routingKey )进行比较,通过规则验证的队列会收到由交换机路由过来的消息。
为了对直接交换有更加清楚的认识,我们采用两个消费者一个生产者的方式来演示(其中有对有错,请注意)。
身份 | 交换机 | 队列 | routeKey |
消费者1 | direct.exchange | direct.queue.one | queue.route.* |
消费者2 | direct.exchange | direct.queue.one | queue.route.one |
生产者 | direct.exchange | 无 | queue.route.one |
/**
* 消费者1
*
* @Tag 直接交换 Direct exchange
*/
public class MQConsumerOne {
public static void main(String[] args) {
try {
consumerMsg("direct.exchange","direct.queue.one","queue.route.*");
} catch (Exception e) {
e.printStackTrace();
}
}
public static void consumerMsg(String exchange,String queue,String routeKey) throws IOException, TimeoutException {
//创建工厂连接
ConnectionFactory connectionFactory = new ConnectionFactory();
//设置连接地址
connectionFactory.setHost("192.168.239.128");
//创建连接
Connection connection = connectionFactory.newConnection();
//创建通道
Channel channel = connection.createChannel();
//声明交换机
channel.exchangeDeclare(exchange, BuiltinExchangeType.DIRECT,false);
//声明队列
channel.queueDeclare(queue,false,false,true,null);
//绑定队列
channel.queueBind(queue,exchange,routeKey,null);
//创建消费者,消费消息
channel.basicConsume(queue, true, (consumerTag, message) -> {
//消费消息
String msg = new String(message.getBody(), "UTF-8");
System.out.println(msg);
}, (consumerTag) -> {
System.out.println(consumerTag);
});
//关闭连接
/* channel.close();
connection.close();*/
}
}
/**
* 消费者2
*
* @Tag 直接交换 Direct exchange
*/
public class MQConsumerTwo {
public static void main(String[] args) {
try {
consumerMsg("direct.exchange","direct.queue.one","queue.route.one");
} catch (Exception e) {
e.printStackTrace();
}
}
public static void consumerMsg(String exchange,String queue,String routeKey) throws IOException, TimeoutException {
//创建工厂连接
ConnectionFactory connectionFactory = new ConnectionFactory();
//设置连接地址
connectionFactory.setHost("192.168.239.128");
//创建连接
Connection connection = connectionFactory.newConnection();
//创建通道
Channel channel = connection.createChannel();
//声明交换机
channel.exchangeDeclare(exchange, BuiltinExchangeType.DIRECT,false);
//声明队列
channel.queueDeclare(queue,false,false,true,null);
//绑定队列
channel.queueBind(queue,exchange,routeKey,null);
//创建消费者,消费消息
channel.basicConsume(queue, true, (consumerTag, message) -> {
//消费消息
String msg = new String(message.getBody(), "UTF-8");
System.out.println(msg);
}, (consumerTag) -> {
System.out.println(consumerTag);
});
//关闭连接
/* channel.close();
connection.close();*/
}
}
/**
* 生产者
*
* @Tag 直接交换 Direct exchange
*/
public class MQProducer {
public static void main(String[] args) {
try {
consumerMsg("direct.exchange","queue.route.one","这么耿直的人,当然是直接交换!");
} catch (Exception e) {
e.printStackTrace();
}
}
public static void consumerMsg(String exchange,String routeKey,String msg) throws IOException, TimeoutException {
//创建工厂连接
ConnectionFactory connectionFactory = new ConnectionFactory();
//设置连接地址
connectionFactory.setHost("192.168.239.128");
//创建连接
Connection connection = connectionFactory.newConnection();
//创建通道
Channel channel = connection.createChannel();
//声明交换机
channel.exchangeDeclare(exchange, BuiltinExchangeType.DIRECT,false);
//创建生产者,发送消息
channel.basicPublish(exchange,routeKey,null,msg.getBytes());
//关闭连接
channel.close();
connection.close();
}
}
1)消费者1的 routeKey:queue.route.*
2)消费者2的 routeKey:queue.route.one
3)生产者的 routeKey:queue.route.one
消费者1的 routeKey 和 生产者的 routeKey 不相等,消费者2的 routeKey 和 生产者的 routeKey完全相等,理论上消费者1不该收到消息,消费者2该收到消息,但是实际结果却和我们的想象恰好相反,为什么呢?
额。。。。突然发现,妈蛋两个消费者的绑定队列竟然一模一样,都是 direct.queue.one !!!
这个时候队列变成了 工作队列,只要有一个消费者的 routeKey 跟生产者的 routeKey 完全匹配,绑定在同一个队列的消费者都会收到消息。
各单位请注意,各单位请注意,演示1失败
身份 | 交换机 | 队列 | routeKey |
消费者1 | direct.exchange | direct.queue | queue.route.* |
消费者2 | direct.exchange | direct.queue.one | queue.route.one |
生产者 | direct.exchange | 无 | queue.route.* |
/**
* 消费者1
*
* @Tag 直接交换 Direct exchange
*/
public class MQConsumerOne {
public static void main(String[] args) {
try {
consumerMsg("direct.exchange","direct.queue","queue.route.*");
} catch (Exception e) {
e.printStackTrace();
}
}
public static void consumerMsg(String exchange,String queue,String routeKey) throws IOException, TimeoutException {
//创建工厂连接
ConnectionFactory connectionFactory = new ConnectionFactory();
//设置连接地址
connectionFactory.setHost("192.168.239.128");
//创建连接
Connection connection = connectionFactory.newConnection();
//创建通道
Channel channel = connection.createChannel();
//声明交换机
channel.exchangeDeclare(exchange, BuiltinExchangeType.DIRECT,false);
//声明队列
channel.queueDeclare(queue,false,false,true,null);
//绑定队列
channel.queueBind(queue,exchange,routeKey,null);
//创建消费者,消费消息
channel.basicConsume(queue, true, (consumerTag, message) -> {
//消费消息
String msg = new String(message.getBody(), "UTF-8");
System.out.println(msg);
}, (consumerTag) -> {
System.out.println(consumerTag);
});
//关闭连接
/* channel.close();
connection.close();*/
}
}
/**
* 消费者2
*
* @Tag 直接交换 Direct exchange
*/
public class MQConsumerTwo {
public static void main(String[] args) {
try {
consumerMsg("direct.exchange","direct.queue.one","queue.route.one");
} catch (Exception e) {
e.printStackTrace();
}
}
public static void consumerMsg(String exchange,String queue,String routeKey) throws IOException, TimeoutException {
//创建工厂连接
ConnectionFactory connectionFactory = new ConnectionFactory();
//设置连接地址
connectionFactory.setHost("192.168.239.128");
//创建连接
Connection connection = connectionFactory.newConnection();
//创建通道
Channel channel = connection.createChannel();
//声明交换机
channel.exchangeDeclare(exchange, BuiltinExchangeType.DIRECT,false);
//声明队列
channel.queueDeclare(queue,false,false,true,null);
//绑定队列
channel.queueBind(queue,exchange,routeKey,null);
//创建消费者,消费消息
channel.basicConsume(queue, true, (consumerTag, message) -> {
//消费消息
String msg = new String(message.getBody(), "UTF-8");
System.out.println(msg);
}, (consumerTag) -> {
System.out.println(consumerTag);
});
//关闭连接
/* channel.close();
connection.close();*/
}
}
/**
* 生产者
*
* @Tag 直接交换 Direct exchange
*/
public class MQProducer {
public static void main(String[] args) {
try {
consumerMsg("direct.exchange","queue.route.*","这么耿直的人,当然是直接交换!");
} catch (Exception e) {
e.printStackTrace();
}
}
public static void consumerMsg(String exchange,String routeKey,String msg) throws IOException, TimeoutException {
//创建工厂连接
ConnectionFactory connectionFactory = new ConnectionFactory();
//设置连接地址
connectionFactory.setHost("192.168.239.128");
//创建连接
Connection connection = connectionFactory.newConnection();
//创建通道
Channel channel = connection.createChannel();
//声明交换机
channel.exchangeDeclare(exchange, BuiltinExchangeType.DIRECT,false);
//创建生产者,发送消息
channel.basicPublish(exchange,routeKey,null,msg.getBytes());
//关闭连接
channel.close();
connection.close();
}
}
1)消费者1的 routeKey:queue.route.*
2)消费者2的 routeKey:queue.route.one
3)生产者的 routeKey:queue.route.*
消费者1的 routeKey 和 生产者的 routeKey 完全相等,消费者2的 routeKey 和 生产者的 routeKey不相等,理论上消费者1应该收到消息,消费者2应该没消息。
除了上面的分析条件外,这里两个消费者的队列很明显不一样,测试结果完全完全跟我们想像的一样,演示成功