Exchanges 交易所
rabbitmq 中消息传递模型的核心思想是:生产者永远不会将任何消息直接发送到队列。实际上,生产者通常甚至不知道消息是否会被传递到任何队列。
相反,生产者只能向交易所(Exchanges)发送消息。交换是一件非常简单的事。一方面,它接收来自生产者的消息,另一方面将它们推送到队列。交易所必须确切知道如何处理它收到的消息,它应该附加到特定队列吗?他应该附加到多个队列吗?或者他应该被丢弃吗?其规则由 交换类型定义(Exchanges type)。
交换类型有几种可供选择:直接direct , 主题topic , 标题headers , 扇出fanout 。创建一个名为logs的fanout交换类型。
channel.exchangedeclare("logs",fanout);
fanout 交换,他只能将收到的所有信息广播到他知道的其他队列中。
回想一下我们之前如何发布消息的:channel.basicPublish("","hello",null,massage.getBytes());
第一个参数就是交换的名称。默认是无名交换就是通过空字符串(“”)来识别的。rabbitmqctl list_exchanges 命令用来查看服务器上所有的交换列表。消息通过routingKey指定的名称的路由到队列(如果存在)。
现在发布到logs交换
channel.basicPublish("logs","hello",null,massage.getBytes());
临时队列 Temporary queues
成功连接到rabbitmq后,默认创建出临时队列(有待考察,一个连接能使用多少个临时队列)。
断开消费者时,临时队列会自动删除。
临时队列只针对流动数据,当你想要在生产者和消费者之间共享队列时使用。
// 获得一个临时队列
channel.queueDeclare();
// 获得临时队列的名称
String queueName = channel.queueDeclare().getQueue();
绑定 Bindings
告诉交换机将消息发送到我们的队列,交换机和队列之间的关系为绑定 Binding
channel.queueBind( queueName , "logs" , " " ); // logs交换机将消息附加到我们的队列中。
rabbitmqctl list_bindings 命令是列出所有的绑定
贴代码
// 生产者
public class SendLog {
final static String EXCHANG_NAME = "logs";
static ConnectionUtil connUtil = new ConnectionUtil();
public static void main(String[] args) throws Exception {
Connection conn = connUtil.getConn();
Channel channel = conn.createChannel();
// 声明交换机 参数1是交换机名称 参数2是交换机类型
channel.exchangeDeclare(EXCHANG_NAME,"fanout");
// 模拟多次发送消息到交换机
for (int i = 0; i<10; i++){
String message = "this is logs Exchange , Number is "+i;
//参数1是交换机名称 2rontingKey秘钥值fanout类型会默认忽略秘钥这里不能写null 4是字节串
channel.basicPublish(EXCHANG_NAME, "",null,message.getBytes());
System.out.println("发送:"+message);
// 模拟 时间间隔 看上去有点忙、
Thread.sleep(1000);
}
// 关闭通道和连接
channel.close();
conn.close();
}
}
// 消费者
public class Receiverlog {
final static String EXCHANG_NAME = "logs";
static ConnectionUtil connUtil = new ConnectionUtil();
public static void main(String[] args) throws Exception {
Connection conn = connUtil.getConn();
Channel channel = conn.createChannel();
// 声明交换机 定义交换机类型
channel.exchangeDeclare(EXCHANG_NAME, "fanout");
// 获取临时队列名称
String queueName = channel.queueDeclare().getQueue();
// 绑定交换机,参数3是routingKey秘钥的值
channel.queueBind(queueName, EXCHANG_NAME, "");
DeliverCallback deliverCallback = (consumerTag, delivery) -> {
String message = new String(delivery.getBody(), "UTF-8");
System.out.println(" 接受请求: '" + message + "'");
};
channel.basicConsume(queueName, true, deliverCallback, consumerTag -> {});
}
}