出处:https://blog.csdn.net/fxq8866/article/details/62049393

RabbitMQ服务器会根据路由键将消息从交换器路由到队列中,如何处理投递到多个队列的情况?这里不同类型的交换器起到了重要的作用。分别是fanout,direct,topic,每一种类型实现了不同的路由算法。

Fanout Exchange 
  不处理路由键。你只需要简单的将队列绑定到交换机上。一个发送到交换机的消息都会被转发到与该交换机绑定的所有队列上。很像子网广播,每台子网内的主机都获得了一份复制的消息。Fanout交换机转发消息是最快的。

生产者

package com.dynamic.rabbitmy.ps;

/**
* Created by fxq on 2017/3/10.
*/

import com.dynamic.rabbitmy.util.ConnectionUtil;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;

/**
* 生产者
*/
public class Send {
private final static String EXCHANGE_NAME="test_exchange_fanout";
public static void main(String[] args) throws Exception{
//获取到连接以及mq通道
Connection connection = ConnectionUtil.getConnection();
Channel channel = connection.createChannel();
//声明交换器
channel.exchangeDeclare(EXCHANGE_NAME,"fanout");//fanout交换器
//消息内容
String message = "商品已经删除,id=1000";
channel.basicPublish(EXCHANGE_NAME,"",null,message.getBytes());
System.out.println(" [x] Sent'"+message+"'" );
channel.close();
connection.close();
}
}

消费者

package com.dynamic.rabbitmy.ps;
/**
* Created by fxq on 2017/3/10.
*/
import com.dynamic.rabbitmy.util.ConnectionUtil;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.QueueingConsumer;
/**
* 消费者
*/
public class Recv
{
private final static String QUEUE_NAME="test_queue_fanout_1";
private final static String EXCHANGE_NAME="test_exchange_fanout";
public static void main(String[] args) throws Exception{
//获取到连接以及通道
Connection connection = ConnectionUtil.getConnection();
Channel channel = connection.createChannel();
channel.queueDeclare(QUEUE_NAME,false,false,false,null);
//绑定队列到交换器
channel.queueBind(QUEUE_NAME,EXCHANGE_NAME,""); //不设置路由键
//统一时刻服务器只会发一条消息给消费者;
channel.basicQos(1);
//定义队列的消费者
QueueingConsumer consumer = new QueueingConsumer(channel);
//监听队列,手动返回完成
channel.basicConsume(QUEUE_NAME,false,consumer);
//获取消息
while (true)
{
QueueingConsumer.Delivery delivery = consumer.nextDelivery();
String message = new String(delivery.getBody());
System.out.println(" 前台系统:'" + message + "'");
Thread.sleep(10);
//手动返回
channel.basicAck(delivery.getEnvelope().getDeliveryTag(),false);
}
}
}

Direct Exchange 
  处理路由键。需要将一个队列绑定到交换机上,要求该消息与一个特定的路由键完全匹配。这是一个完整的匹配。如果一个队列绑定到该交换机上要求路由键 “test”,则只有被标记为“test”的消息才被转发,不会转发test.aaa,也不会转发dog.123,只会转发test。

生产者:

package com.dynamic.rabbitmy.routing;

/**
* Created by fxq on 2017/3/10.
*/

import com.dynamic.rabbitmy.util.ConnectionUtil;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;

/**
* 生产者
*/
public class Send {
private final static String EXCHANGE_NAME="test_exchange_direct";
public static void main(String[] args) throws Exception{
//获取到连接以及通道
Connection connection = ConnectionUtil.getConnection();
Channel channel = connection.createChannel();
//声明exchange
channel.exchangeDeclare(EXCHANGE_NAME,"direct");
//消息内容
String message = "删除商品,id = 1001";
channel.basicPublish(EXCHANGE_NAME,"delete",null,message.getBytes()); //此处delete为路由键;
System.out.println(" [x] Sent '"+ message+"'");
channel.close();
connection.close();
}
}

生产者:

package com.dynamic.rabbitmy.routing;

/**
* Created by fxq on 2017/3/10.
*/

import com.dynamic.rabbitmy.util.ConnectionUtil;
import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.QueueingConsumer;

/**
* 消费者1
*/
public class Recv {

private final static String QUEUE_NAME="test_queue_direct_1";
private final static String EXCHANGE_NAME="test_exchange_direct";
public static void main(String[] args) throws Exception{
//获取连接以及mq通道
Connection connection = ConnectionUtil.getConnection();
Channel channel = connection.createChannel();
//声明队列
channel.queueDeclare(QUEUE_NAME,false,false,false,null);
//绑定队列到交换机;
channel.queueBind(QUEUE_NAME,EXCHANGE_NAME,"update"); //匹配路由键为update
channel.queueBind(QUEUE_NAME,EXCHANGE_NAME,"delete"); //匹配路由键是delete
//同一时刻服务器只会发送一条消息给消费者;
channel.basicQos(1);
QueueingConsumer consumer = new QueueingConsumer(channel);
//监听队列,手动返回完成
channel.basicConsume(QUEUE_NAME,false,consumer);
//获取消息
while (true)
{
QueueingConsumer.Delivery delivery = consumer.nextDelivery();
String message = new String(delivery.getBody());
System.out.println("前台系统:'"+message+"'");
Thread.sleep(10);
channel.basicAck(delivery.getEnvelope().getDeliveryTag(),false);
}
}
}

该绑定在交换器上的队列,它可以匹配delete,update的路由键,但不是能匹配insert;必须和生产者声明是一模一样;

Topic Exchange 
  将路由键和某模式进行匹配。此时队列需要绑定要一个模式上。符号“#”匹配一个或多个词,符号“*”匹配不多不少一个词。因此“audit.#”能够匹配到“audit.irs.corporate”,但是“audit.*” 只会匹配到“audit.irs”。

生产者:

package com.dynamic.rabbitmy.topic;

/**
* Created by fxq on 2017/3/10.
*/

import com.dynamic.rabbitmy.util.ConnectionUtil;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
/**
* 发送者
*/
public class Send {
private final static String EXCHANGE_NAME="test_exchange_topic" ;
public static void main(String[] args) throws Exception{
//获取到连接以及mq通道
Connection connection = ConnectionUtil.getConnection();
Channel channel = connection.createChannel();
//声明exchange
channel.exchangeDeclare(EXCHANGE_NAME,"topic");
//消息内容
String message = "插入商品,id=100";
//发布消息
channel.basicPublish(EXCHANGE_NAME,"item.insert",null,message.getBytes());
System.out.println(" [x] Sent '"+message + "'");
channel.close();
connection.close();
}
}

消费者:

package com.dynamic.rabbitmy.topic;

import com.dynamic.rabbitmy.util.ConnectionUtil;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.QueueingConsumer;
import com.sun.media.sound.SF2InstrumentRegion;

/**
* Created by fxq on 2017/3/10.
*/
public class Recv2 {

private final static String QUEUE_NAME="test_queue_topic2";
private final static String EXCHANGE_NAME="test_exchange_topic" ;
public static void main(String[] args) throws Exception{
//获得连接和mq通道
Connection connection = ConnectionUtil.getConnection();
Channel channel = connection.createChannel();
//声明通道
channel.queueDeclare(QUEUE_NAME,false,false,false,null);
//绑定exchange
channel.queueBind(QUEUE_NAME,EXCHANGE_NAME,"item.#"); //使用item.# 匹配所有的以item开头的
//同一时刻服务器只能发送一条消息给消费者;
channel.basicQos(1);
//声明消费者
QueueingConsumer consumer = new QueueingConsumer(channel);
//监控队列,设置手动完成
channel.basicConsume(QUEUE_NAME,false,consumer);
while (true)
{
QueueingConsumer.Delivery delivery = consumer.nextDelivery();
String message = new String(delivery.getBody());
System.out.println("搜索系统 '" + message + "'");
Thread.sleep(10);
channel.basicAck(delivery.getEnvelope().getDeliveryTag(),false);
}
}
}

以上就是三种交换器的类型以及他们的使用场景,基于消息的路由键和交换器的类型,服务器会决定将消息投递到那个队列中。

【RabbitMQ】三种类型交换器 Fanout,Direct,Topic(转)的更多相关文章

  1. RabbitMQ三种Exchange模式(fanout,direct,topic)的特性 -摘自网络

    RabbitMQ中,所有生产者提交的消息都由Exchange来接受,然后Exchange按照特定的策略转发到Queue进行存储 RabbitMQ提供了四种Exchange:fanout,direct, ...

  2. RabbitMQ三种Exchange模式(fanout,direct,topic)的性能比较

    RabbitMQ中,所有生产者提交的消息都由Exchange来接受,然后Exchange按照特定的策略转发到Queue进行存储 RabbitMQ提供了四种Exchange:fanout,direct, ...

  3. RabbitMQ三种Exchange模式(fanout,direct,topic)的性能比较(转)

    RabbitMQ中,所有生产者提交的消息都由Exchange来接受,然后Exchange按照特定的策略转发到Queue进行存储 RabbitMQ提供了四种Exchange:fanout,direct, ...

  4. [转]RabbitMQ三种Exchange模式(fanout,direct,topic)的性能比较

    RabbitMQ中,所有生产者提交的消息都由Exchange来接受,然后Exchange按照特定的策略转发到Queue进行存储 RabbitMQ提供了四种Exchange:fanout,direct, ...

  5. RabbitMQ三种Exchange模式

    RabbitMQ中,所有生产者提交的消息都由Exchange来接受,然后Exchange按照特定的策略转发到Queue进行存储 RabbitMQ提供了四种Exchange:fanout,direct, ...

  6. 【转】RabbitMQ三种Exchange模式

    [转]RabbitMQ三种Exchange模式 RabbitMQ中,所有生产者提交的消息都由Exchange来接受,然后Exchange按照特定的策略转发到Queue进行存储 RabbitMQ提供了四 ...

  7. 8、RabbitMQ三种Exchange模式(fanout,direct,topic)的性能比较

    RabbitMQ三种Exchange模式(fanout,direct,topic)的性能比较 RabbitMQ中,除了Simple Queue和Work Queue之外的所有生产者提交的消息都由Exc ...

  8. 链路层三种类型的MAC地址

    若需要转载,请注明出处. 我们知道,链路层都是以MAC地址来进行通信双方的地址标识的,如下图:在应用中根据接收方的多寡来进行划分,可分为以下三种: 单播(Unicast) 多播(Multicast) ...

  9. matlab for循环的三种类型

    学习了一半了,发现一个好网站,就是我想写这篇博客用的,网络真是个好东西!纪念下国庆啦 网址:http://www.yiibai.com/matlab/matlab_for_loop.html ---- ...

随机推荐

  1. 【go语言实现服务器接收http请求以及出现泄漏时的解决方案】

    一.关于基础的程序的实现 刚开始的时候程序是这样实现的: // Hello package main import ( "database/sql" "fmt" ...

  2. FortiGate设备管理

    1.Web管理 1.FortiGate出厂配置 默认地址为192.168.1.99,可以通过https的方式进行web管理(默认用户名admin,密码为空).不同型号设备用于管理的接口略有不同,如: ...

  3. sql语句Order by 报错列名不明确

    select top 10 column1,column2,column3 from table1 where table1.id not in(select top 0 table1.id from ...

  4. win下apache的error.log和access.log文件过大

    在httpd.conf中修改ErrorLog和CustomLog的配置 ErrorLog "|E:/apache2.2/bin/rotatelogs.exe E:/apache2.2/log ...

  5. JFinal Web开发学习(三)前后台路由设计

    效果图: 一.写控制器 1.在controller包中新建AdminController后台控制器,继承Controller,实现一个index方法,作为的处理方法. /admin 后面,这个控制器中 ...

  6. Django 前端Wbe框架

    Web框架本质及第一个Django实例   Web框架本质 我们可以这样理解:所有的Web应用本质上就是一个socket服务端,而用户的浏览器就是一个socket客户端. 这样我们就可以自己实现Web ...

  7. 【转】我为什么把think in java 读了10遍

    我在想写这篇博文之前,就曾经对我媳妇(她是做web前端的)讲,我把think in java看了几次几次,媳妇那时就用很羡慕和莫名的眼神看着我说,你真有毅力,我当时就蒙了,我以为她会说,你现在基础一定 ...

  8. Liunx 硬盘分区

    1)什么要进行硬盘分区:a) 更容易管理和控制系统,因为相关的文件和目录都放在一个分区中.b) 系统效率更高.c) 可以限制用户使用硬盘的份额(磁盘空间的大小).d) 更容易备份和恢复. 2)硬盘的逻 ...

  9. ssm介绍

    1.Spring     Spring是一个开源框架,Spring是于2003 年兴起的一个轻量级的Java 开发框架,由Rod Johnson 在其著作Expert One-On-One J2EE ...

  10. Android.Tools.Eclipse hangs at the Android SDK Content Loader

    Eclipse hangs at the Android SDK Content Loader http://stackoverflow.com/questions/13489141/eclipse- ...