RabbitMQ消息队列(四)

本文介绍了RabbitMQ的三种消息队列模式:fanout、routing和topics。fanout模式实现广播式发送,每个消费者都能接收到所有消息。routing模式通过路由键将消息发送到特定队列。topics模式允许使用通配符进行模糊匹配,增强了路由灵活性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.fanout 发布/订阅
在上一篇中队列都指定了名称,现在我们需要所有的日志信息,而不只是其中的一个。如果要做这样的队列,我们需要2件事,一个就是获取一个新的空的队列,这样我就需要创建一个随机名称的队列,最好让服务器帮我们做出选择,第一个就是我们断开用户的队列,应该自动进行删除。

这里写图片描述

生产者:

/**
 * 发布/订阅 生产者
 */
public class EmitLog {
    public static final String EXCHANGE_NAME = "logs";

    public static void main(String[] args) throws Exception {
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        Connection connection = factory.newConnection();
        Channel channel = connection.createChannel();
        channel.exchangeDeclare(EXCHANGE_NAME,"fanout");//fanout表示分发,所有的消费者得到同样的队列信息
        for (int i = 0 ; i<10;i++){
            String message = "hello fanout "+i;
            channel.basicPublish(EXCHANGE_NAME,"",null,message.getBytes("utf-8"));
            System.out.println("emitLog send '"+message+"'");
        }
        channel.close();
        connection.close();
    }
}

消费者(两个消费者代码一样):

/**
 * 消费者
 */
public class ReceiveLogs1 {
    public static final String EXCHANGE_NAME = "logs";

    public static void main(String[] args) throws Exception {
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        Connection connection = factory.newConnection();
        Channel channel = connection.createChannel();
        channel.exchangeDeclare(EXCHANGE_NAME,"fanout");
        //产生一个随机的队列名称
        String queue = channel.queueDeclare().getQueue();
        //对队列进行绑定
        channel.queueBind(queue,EXCHANGE_NAME,"");
        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");
                System.out.println("ReceiveLogs1 Received '" + message + "'");
            }
        };
        channel.basicConsume(queue,true,consumer); //从队列中删除
    }
}

查看结果:
生产者:
这里写图片描述

消费者1:
这里写图片描述

消费者2:
这里写图片描述

2.Routing 按路线发布接收

这里写图片描述

生产者:

/**
 * routing key 匹配,Message就会被传递到相应的queue中
 */
public class RoutingSendDirect {
    private static final String EXCHANGE_NAME = "direct_logs";
    // 路由关键字
    private static final String[] routingKeys = new String[]{"info" ,"warning", "error"};

    public static void main(String[] args) throws Exception {
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        Connection connection = factory.newConnection();
        Channel channel = connection.createChannel();
        //声明交换机,注意是direct
        channel.exchangeDeclare(EXCHANGE_NAME,"direct");
        //发送信息
        for (String key : routingKeys){
            String message = "RoutingSendDirect Send the message level:" + key;
            channel.basicPublish(EXCHANGE_NAME,key,null,message.getBytes("utf-8"));
            System.out.println("RoutingSendDirect Send"+key +"':'" + message);
        }
        channel.close();
        connection.close();
    }
}

消费者1:

/**
 * 消费者1
 */
public class ReceiveLogsDirect1 {
    // 交换器名称
    private static final String EXCHANGE_NAME = "direct_logs";
    // 路由关键字
    private static final String[] routingKeys = new String[]{"error"};

    public static void main(String[] args)throws Exception {
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        Connection connection = factory.newConnection();
        Channel channel = connection.createChannel();
        //声明交换器
        channel.exchangeDeclare(EXCHANGE_NAME,"direct");
        //获取匿名队列名称
        String queue = channel.queueDeclare().getQueue();
        //根据路由关键字进行绑定
        for (String key : routingKeys) {
            channel.queueBind(queue,EXCHANGE_NAME,key);
            System.out.println("ReceiveLogsDirect1 exchange:"+EXCHANGE_NAME+"," +
                    " queue:"+channel+", BindRoutingKey:" + key);
        }
        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");
                System.out.println("ReceiveLogsDirect1 Received '" + envelope.getRoutingKey() + "':'" + message + "'");
            }
        };
        channel.basicConsume(queue,true,consumer);

    }
}

消费者2:

/**
 * 消费者2
 */
public class ReceiveLogsDirect2 {
    // 交换器名称
    private static final String EXCHANGE_NAME = "direct_logs";
    // 路由关键字
    private static final String[] routingKeys = new String[]{"info" ,"warning","error"};

    public static void main(String[] args)throws Exception {
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        Connection connection = factory.newConnection();
        Channel channel = connection.createChannel();
        //声明交换器
        channel.exchangeDeclare(EXCHANGE_NAME,"direct");
        //获取匿名队列名称
        String queue = channel.queueDeclare().getQueue();
        //根据路由关键字进行绑定
        for (String key : routingKeys) {
            channel.queueBind(queue,EXCHANGE_NAME,key);
            System.out.println("ReceiveLogsDirect2 exchange:"+EXCHANGE_NAME+"," +
                    " queue:"+channel+", BindRoutingKey:" + key);
        }
        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");
                System.out.println("ReceiveLogsDirect2 Received '" + envelope.getRoutingKey() + "':'" + message + "'");
            }
        };
        channel.basicConsume(queue,true,consumer);

    }
}

查看结果:
生产者:
这里写图片描述

消费者1:

这里写图片描述

消费者2:

这里写图片描述

3.Topics 模糊匹配
* : 可以替代一个词
# :可以替代0个或更多词

这里写图片描述

生产者:

/**
 * 模糊匹配队列 
 * 生产者
 */
public class TopicSend {
    public static final String EXCHANGE_NAME = "topic_logs";

    public static void main(String[] args) throws Exception {
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        Connection connection = factory.newConnection();
        Channel channel = connection.createChannel();
        //声明一个匹配模式的交换机
        channel.exchangeDeclare(EXCHANGE_NAME,"topic");
        //待发送的消息
        String[] routingKeys=new String[]{
                "quick.orange.rabbit",
                "lazy.orange.elephant",
                "quick.orange.fox",
                "lazy.brown.fox",
                "quick.brown.fox",
                "quick.orange.male.rabbit",
                "lazy.orange.male.rabbit"
        };
        //发送消息
        for (String key:routingKeys ) {
            String message = "From "+key+" routingKey' s message!";
            channel.basicPublish(EXCHANGE_NAME,key,null,message.getBytes("utf-8"));
            System.out.println("TopicSend Sent '" + key + "':'" + message + "'");
        }
        channel.close();
        connection.close();
    }
}

消费者1:

/**
 * 消费者1
 */
public class ReceiveLogsTopic1 {
    private static final String EXCHANGE_NAME = "topic_logs";

    public static void main(String[] args) throws Exception {
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        Connection connection = factory.newConnection();
        Channel channel = connection.createChannel();
        //声明一个匹配模式的交换机
        channel.exchangeDeclare(EXCHANGE_NAME,"topic");
        String queue = channel.queueDeclare().getQueue();
        //路由关键字
        String[] routingKeys = new String[]{"*.orange.*"};
        //绑定路由
        for (String key : routingKeys){
            channel.queueBind(queue,EXCHANGE_NAME,key);
            System.out.println("ReceiveLogsTopic1 exchange:" + EXCHANGE_NAME + ", queue:" + queue + ", BindRoutingKey:" + key);
        }
        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");
                System.out.println("ReceiveLogsTopic1 Received '" + envelope.getRoutingKey() + "':'" + message + "'");
            }
        };
        channel.basicConsume(queue,true,consumer);
    }
}

消费者2:

/**
 * 消费者2
 */
public class ReceiveLogsTopic2 {
    private static final String EXCHANGE_NAME = "topic_logs";

    public static void main(String[] args) throws Exception {
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        Connection connection = factory.newConnection();
        Channel channel = connection.createChannel();
        //声明一个匹配模式的交换机
        channel.exchangeDeclare(EXCHANGE_NAME,"topic");
        String queue = channel.queueDeclare().getQueue();
        //路由关键字
        String[] routingKeys = new String[]{"*.*.rabbit", "lazy.#"};
        //绑定路由
        for (String key : routingKeys){
            channel.queueBind(queue,EXCHANGE_NAME,key);
            System.out.println("ReceiveLogsTopic2 exchange:" + EXCHANGE_NAME + ", queue:" + queue + ", BindRoutingKey:" + key);
        }
        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");
                System.out.println("ReceiveLogsTopic2 Received '" + envelope.getRoutingKey() + "':'" + message + "'");
            }
        };
        channel.basicConsume(queue,true,consumer);
    }
}

查看结果:
生产者:
这里写图片描述

消费者1:
这里写图片描述

消费者2:
这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值