RabbitMQ的exchange模式有:fanout(路由器模式)、direct(指定模式,RabbitMQ的默认模式)、topic(主题)、headers(不常用)。
direct模式:指定exchange为direct,发送者发送消息时设置routing_key(路由键),消费者绑定exchange并指定bing_key与消息的routing_key相同,此时消息发送到交换器,消费者绑定的queue接收到消息,再由routing_key决定哪个消费者消费消息,没有对应的routing_key则消息丢失。
消费者根据设置的binding_key(绑定键)来选择性的接收自身业务关心的massage。
模式如下图:
如图:队列Q1,Q2 bind到交换器X,Q1的bind_key为monkey,Q2的bind_key为cat、dog,如果发送者将消息发送到交换器X的routing_key设为monkey,则会被Q1接收,如果设置为cat/dog则会被Q2接收,其他发送到exchange上的消息则会被丢弃。
如图:当指定的routing_key不存在时,消息会被丢弃
这时,我们看exchange的Bindings时,是没有绑定关系的
下图是存在绑定关系并成功消费消息时exchange的bingings的情况,模拟的是同一queue存在两个routing_key的情况。
完整的代码如下:
先启动消费者,exchange以及bind关系由消费者初始化
public class DirectReceive {
private static final String EXCHANGE_NAME = "direct_exchange";
private static final String ROUTING_KEY1 = "direct_routing_key1";
private static final String ROUTING_KEY2 = "direct_routing_key2";
private static final Logger LOGGER = LoggerFactory.getLogger(DirectReceive.class);
private static Channel buildChange(){
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
Connection connection;
Channel channel = null;
try {
connection = factory.newConnection();
//create a channel
channel = connection.createChannel();
} catch (IOException|TimeoutException e) {
LOGGER.info("connection or channel create error:{}",e.getMessage());
}
return channel;
}
private void receiveMsg(Channel channel){
String queueName = null;
try {
//create default queue
queueName = channel.queueDeclare().getQueue();
//bind queue to exchange and build routing_key
channel.queueBind(queueName, EXCHANGE_NAME, ROUTING_KEY1);
channel.queueBind(queueName, EXCHANGE_NAME, ROUTING_KEY2);
} catch (IOException e) {
LOGGER.info("queue bind error:{}",e.getMessage());
}
//create consumer
Consumer consumer = new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag,
Envelope envelope,
AMQP.BasicProperties properties,
byte[] body) throws IOException {
String message = new String(body, "UTF-8");
LOGGER.info("receive message:{}", message);
channel.basicAck(envelope.getDeliveryTag(), true);
}
};
try {
//consume message
channel.basicConsume(queueName, true, consumer);
} catch (IOException e) {
LOGGER.info("receive massage error:{}",e.getMessage());
}
}
public static void main(String []args) throws IOException {
DirectReceive directReceive = new DirectReceive();
Channel channel = DirectReceive.buildChange();
directReceive.receiveMsg(channel);
}
}
生产者:
public class DirectSender {
private static final String EXCHANGE_NAME = "direct_exchange";
public static void main(String []args) throws IOException, TimeoutException {
//create rabbit connection factory
ConnectionFactory factory = new ConnectionFactory();
//crate a connect to rabbit server
Connection connection = factory.newConnection();
//create channel
Channel channel = connection.createChannel();
String message = "this is a direct message";
//send message to rabbit exchange
channel.basicPublish(EXCHANGE_NAME, "direct_routing_key1", null, ("message1:"+message).getBytes());
channel.basicPublish(EXCHANGE_NAME, "direct_routing_key2", null, ("message2:"+message).getBytes());
channel.close();
factory.clone();
}
}