RabbitMQ中的消息传递模型的核心思想是,生产者从不将任何消息直接发送到队列。实际上,生产者通常甚至不知道是否将消息传递到任何队列。
相反,生产者只能将信息发送到交换机。交换是一件非常简单的事情。一方面,它收到来自生产者的消息,另一方将它们推送到队列。交换机必须准确知道接收到的消息如何处理。应该附加到特定队列吗?应该附加到很多队列吗?或者应该丢弃。其规则由交换类型定义 。
下面我就介绍下fanout类型的交换机。
Fanout交换机的交换非常简单,就是将你收到的消息广播到所有知道的队列。
当一个消费者对应一个交换机的时候,我们可以实现消费者共享这个消息,下面是代码
交换机绑定队列既可以在生产者中实现,也可以在消费者中实现,此次我是在生产者中绑定了两个队列,再构造两个消费者与队列相对应
绑定
//将队列绑定到交换机上
channel.queueBind(QUEUE_NAME,EXCHANGE_NAME,"");
channel.queueBind(QUEUE_NAME2,EXCHANGE_NAME,"");
生产者代码如下:
package MQ.Exchange.Fanout;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
importcom.rabbitmq.client.ConnectionFactory;
public classNewTask {
private final static String EXCHANGE_NAME="logs";
private final static String QUEUE_NAME ="hello_fanout2";
private final static String QUEUE_NAME2 ="hello_fanout3";
public static void main(String[] args)throws IOException,TimeoutException {
// 创建连接连接到MabbitMQ
ConnectionFactoryfactory = newConnectionFactory();
// 设置MabbitMQ所在主机ip或者主机名
factory.setHost("127.0.0.1");
factory.setUsername("yuanh");
factory.setPassword("yuanh");
factory.setPort(5672);
factory.setVirtualHost("y_yuanh");
Connectionconnection = factory.newConnection();
// 创建一个频道
Channelchannel = connection.createChannel();
// 声明队列、设置队列持久化
boolean durable =true;
channel.queueDeclare(QUEUE_NAME, durable,false,false,null);
channel.queueDeclare(QUEUE_NAME2, durable,false,false,null);
// 声明fanout交换机、设置持久化
boolean durable2 =true;
channel.exchangeDeclare(EXCHANGE_NAME,"fanout",durable2);
//将队列绑定到交换机上
channel.queueBind(QUEUE_NAME,EXCHANGE_NAME,"");
channel.queueBind(QUEUE_NAME2,EXCHANGE_NAME,"");
Stringmessage = getMessage(args);
// 将消息放到队列里面
// channel.basicPublish("", QUEUE_NAME, null,message.getBytes());
// 将消息放到交换机上
channel.basicPublish(EXCHANGE_NAME,"",null,message.getBytes());
System.out.println("发送 '" + message +"'");
// 关闭通道和连接
channel.close();
connection.close();
}
private static StringgetMessage(String[] strings) {
if (strings.length < 1)
return"Hello World..!";
return joinStrings(strings," ");
}
private static StringjoinStrings(String[] strings, String delimiter) {
int length = strings.length;
if (length == 0)
return"";
StringBuilderwords = newStringBuilder(strings[0]);
for (int i = 1; i < length;i++) {
words.append(delimiter).append(strings[i]);
}
return words.toString();
}
}
让各个队列对应一个消费者,进行消费
package MQ.Exchange.Fanout;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.QueueingConsumer;
@SuppressWarnings("deprecation")
/**
* @Title: MQ.WorkQueues.Worker.java
* @Package MQ.WorkQueues
* @Description:TODO(MQ消息发送到fanout的交换机上)
* @Copyright: Copyright (c) 2017 YUANH All Rights Reserved
* @authoryuanh
* @date 2017-5-10下午3:48:59
*/
public classWorkerResponse {
private final static String QUEUE_NAME ="hello_fanout2";
//private final static String QUEUE_NAME ="hello_fanout3";
// private final static String EXCHANGE_NAME ="logs";
public static void main(String[] argv)throws Exception {
// 创建连接连接到MabbitMQ
ConnectionFactoryfactory = newConnectionFactory();
// 设置MabbitMQ所在主机ip或者主机名
factory.setHost("127.0.0.1");
factory.setUsername("yuanh");
factory.setPassword("yuanh");
factory.setPort(5672);
factory.setVirtualHost("y_yuanh");
Connectionconnection = factory.newConnection();
Channelchannel = connection.createChannel();
// 1声明队列、设置队列持久化
boolean durable =true;
channel.queueDeclare(QUEUE_NAME, durable,false,false,null);
QueueingConsumerconsumer = newQueueingConsumer(channel);
// 2消费者指定消费队列,打开应答机制,注意false才是打开手动应对,true为自动应答
boolean ack =false;
channel.basicConsume(QUEUE_NAME, ack, consumer);
// 3消费者设置最大服务转发消息数量,公平转发
int prefetchCount = 1;
channel.basicQos(prefetchCount);
try {
while (true) {
QueueingConsumer.Deliverydelivery = consumer.nextDelivery();
Stringmessage = newString(delivery.getBody());
System.out.println("接收 '" + message +"'");
try {
doWork(message);
}finally{
System.out.println("结束");
// 另外需要在每次处理完成一个消息后,手动发送一次应答(ack=false)。
channel.basicAck(delivery.getEnvelope().getDeliveryTag(),
false);
}
}
}catch(Exception e) {
channel.close();
connection.close();
}
}
private static void doWork(String task)throws InterruptedException {
for (char ch : task.toCharArray()){
if (ch =='.')
Thread.sleep(1000);
}
}
}