rabbitMQ--五种消息模型

基本消息模型

在这里插入图片描述

生产者发送一条消息给消息队列,消费者被动接收消息

代码:

生产者

public class Producer {
    public static void main(String[] args) {
        /***
         * 1 创建连接工程
         * 2 创建连接Connection
         * 3 通过连接获取通道
         * 4 通过连接创建交换机,申明队列,绑定关系,路由可以,发送消息和接收消息
         * 5 准备消息
         * 6 发送消息
         * 7 关闭连接
         * 8 关闭通道
         */

        ConnectionFactory connectionFactory = new ConnectionFactory();
        connectionFactory.setHost("192.168.0.172");
        connectionFactory.setPort(5672);
        connectionFactory.setUsername("admin");
        connectionFactory.setPassword("admin");
        connectionFactory.setVirtualHost("/");

        Connection connection = null;
        Channel channel = null;
        try {
            connection = connectionFactory.newConnection("生产者");
            channel = connection.createChannel();
            String queueName = "queue";
            /***
             * @param1 队列名称
             * @param2 是否持久化(false 非持久化,true 持久化)
             * @param3 排他性 是否是独占
             * @param4 是否自动删除  随着最后一个消费者消息完毕以后是否吧队列自动删除
             * @param5 携带附属参数
             */
            channel.queueDeclare(queueName, false, false, false, null);
            String message = "Hello world";
            channel.basicPublish("", queueName, null, message.getBytes());

            System.out.println("message has been send");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if(channel!=null && channel.isOpen()){
                try {
                    channel.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            if(connection!=null && connection.isOpen()){
                try {
                    connection.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }


        }
    }
}

消费者

public class Recv {
    public static void main(String[] args) {
        ConnectionFactory connectionFactory = new ConnectionFactory();

        connectionFactory.setHost("192.168.0.172");
        connectionFactory.setPort(5672);
        connectionFactory.setUsername("admin");
        connectionFactory.setPassword("admin");
        connectionFactory.setVirtualHost("/");


        Connection recvConnection=null;
        Channel channel=null;
        try {
            recvConnection = connectionFactory.newConnection("recv");
            channel=recvConnection.createChannel();

            channel.queueDeclare("queue",false,false,false,null);
            System.out.println("接收消息");

            channel.basicConsume("queue",true,( s,  delivery)->{
                String message = new String(delivery.getBody(), "UTF-8");
                System.out.println("接收到消息"+message);
            },consumerTag->{});



        } catch (IOException e) {
            e.printStackTrace();
        } catch (TimeoutException e) {
            e.printStackTrace();
        }
    }
}

执行结果
在这里插入图片描述
在这里插入图片描述

work消息模型

在这里插入图片描述

将密集任务发送到消息队列,由多个消费者进行监听消费,每个消息只能由一个消费者接收

代码

生产者,生产50条消息

public class Producer {
    public static void main(String[] args) {
        ConnectionFactory connectionFactory = new ConnectionFactory();
        connectionFactory.setHost("192.168.0.172");
        connectionFactory.setUsername("admin");
        connectionFactory.setPassword("admin");

        try(Connection connection = connectionFactory.newConnection();
            Channel channel = connection.createChannel()) {

            String queueName="work_queue";
            String exchangeName="work_exchange";

            channel.exchangeDeclare(exchangeName,"direct");
            channel.queueDeclare(queueName,false,false,false,null);
            for(int i=0;i<50;i++){
                String msg="hello workQueue_tianya_"+i;
                channel.basicPublish("",queueName,false,false,null,msg.getBytes());
            }

            System.out.println("msg has been send!");

        } catch (IOException e) {
            e.printStackTrace();
        } catch (TimeoutException e) {
            e.printStackTrace();
        }finally {

        }

    }
}

消费者1,消费者2

public class Recv {
    public static void main(String[] args) throws IOException, TimeoutException {
        ConnectionFactory connectionFactory = new ConnectionFactory();
        connectionFactory.setHost("192.168.0.172");
        connectionFactory.setUsername("admin");
        connectionFactory.setPassword("admin");


        String queueName = "work_queue";
        Connection connection = connectionFactory.newConnection();
        final Channel channel = connection.createChannel();
        channel.queueDeclare(queueName, false, false, false, null);
           /* final DeliverCallback deliverCallback = new DeliverCallback() {
                @Override
                public void handle(String s, Delivery delivery) throws IOException {
                    final String message = new String(delivery.getBody(), "UTF-8");
                    System.out.println("[1] Received " + message);
                    doWork(message);
                    //手动确认
                    channel.basicAck(delivery.getEnvelope().getDeliveryTag(),false);
                }
            };*/
        DefaultConsumer consumer = new DefaultConsumer(channel) {
            // 获取消息,并且处理,这个方法类似事件监听,如果有消息的时候,会被自动调用

            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                // body 即消息体
                String msg = new String(body);
                System.out.println(" [消费者1] received : " + msg + "!");
                doWork(msg);
                // 手动ACK
//                channel.basicAck(envelope.getDeliveryTag(), false);
            }
        };

        channel.basicConsume(queueName, true, consumer);


    }

    public static void doWork(String msg) {
        final String[] msgs = msg.split("_");
        int time = Integer.parseInt(msgs[2]);
        try {
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

先启动两个消费者,在启动生产者,结果如下

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7eX5OZrx-1628821763609)(图片/image-20210727111818642.png)]
在这里插入图片描述
可以看到两个消费者交替执行。

可以看出以上为轮训模式,当消费者之间执行的效率不一样时,则应当按照“消费者的消费水平”进行分发消息

公平模式

int prefetchCount =1  
channel.basicQos(prefetchCount);

表示mq不要像消费端发送多于prefetchCount条消息,直到消息确认全部处理完毕在重新发送

在这里插入图片描述
在这里插入图片描述

订阅模式

示意图
在这里插入图片描述

生产者不直接将消息发送到指定的队列中,而是将消息发送的交换机,有交换机根据当前交换机类型将消息发送到特定的队列中。

订阅模式–Fanout

广播模式,该模式下,交换机会将消息转发到所有与交换机绑定的队列中
在这里插入图片描述
代码:

生产者

public class Producer {
    public static void main(String[] args) throws Exception {
        final Connection connection = RabbitmqUtil.getConnection();
        final Channel channel = RabbitmqUtil.getChannel();
        String exchangeName="logs";
        //声明交换机
        channel.exchangeDeclare(exchangeName,"fanout");

        String message="info: Hello world";
        channel.basicPublish(exchangeName,"",null,message.getBytes());
        channel.close();
        connection.close();

    }

}

消费者1,2

public class Recv1 {
    public static void main(String[] args) throws Exception {
        final Connection connection = RabbitmqUtil.getConnection();
        final Channel channel = RabbitmqUtil.getChannel();
        String exchangeName = "logs";
        String queueName = "logs_queue1";
        //声明队列
        channel.queueDeclare(queueName, false, false, false, null);
        //绑定队列和交换机
        channel.queueBind(queueName,exchangeName,"");

        channel.basicConsume(queueName,false,new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
               String message=new String(body);
                System.out.println("消费者[1] 接收消息:"+message);
            }
        });

    }

}

执行结果

在这里插入图片描述
在这里插入图片描述
通过管理页面查看,队列已于交换机绑定

在这里插入图片描述

订阅模式–Topic

主题模式,通过通配符(*,#)进行模糊匹配,根据routingKey将消息路由到不同的队列中

‘#’ 0个或多个单词

‘*’ 只有一个单词
在这里插入图片描述

代码:

生产者

public class Producer {
    public static void main(String[] args) throws Exception {
        final Connection connection = RabbitmqUtil.getConnection();
        final Channel channel = RabbitmqUtil.getChannel();
        String exchangeName="topic_logs";
        channel.exchangeDeclare(exchangeName,"topic");

        String message1="勇敢牛牛,不怕困难";
        String message2="牛奶真好喝";
        channel.basicPublish(exchangeName,"brave.cow",null,message1.getBytes());
        channel.basicPublish(exchangeName,"brave.cow.milk",null,message2.getBytes());
        channel.close();
        connection.close();

    }

}

消费者

public class Recv1 {
    public static void main(String[] args) throws Exception {
        final Connection connection = RabbitmqUtil.getConnection();
        final Channel channel = RabbitmqUtil.getChannel();
        String exchangeName = "topic_logs";
        String queueName = "logs_queue1";
        channel.queueDeclare(queueName, false, false, false, null);
        channel.queueBind(queueName,exchangeName,"#.cow");

        channel.basicConsume(queueName,false,new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
               String message=new String(body);
                System.out.println("消费者[1] 接收消息:"+message);
                channel.basicAck(envelope.getDeliveryTag(),false);
            }
        });

    }

}
public class Recv2 {
    public static void main(String[] args) throws Exception {
        final Connection connection = RabbitmqUtil.getConnection();
        final Channel channel = RabbitmqUtil.getChannel();
        String exchangeName = "topic_logs";
        String queueName = "logs_queue2";
        channel.queueDeclare(queueName, false, false, false, null);
        channel.queueBind(queueName,exchangeName,"#.cow.*");

        channel.basicConsume(queueName,false,new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
               String message=new String(body);
                System.out.println("消费者[2] 接收消息:"+message);
                channel.basicAck(envelope.getDeliveryTag(),false);
            }
        });
      /*  channel.close();
        connection.close();*/

    }

}

执行结果
在这里插入图片描述
在这里插入图片描述

订阅模式–Direct

当使用fanout模式时,发布者发布消息,所有的消费者都能获取到消息,而在此模式下,消费者只能获取某种特定的消息,如示意图所示,C1只能获取routingKey为error的日志,C2只能获取routingKey为info,error和warning的日志。
在这里插入图片描述
代码:

生产者

public class Producer {
    public static void main(String[] args) throws Exception {
        final Connection connection = RabbitmqUtil.getConnection();
        final Channel channel = RabbitmqUtil.getChannel();
        String exchangeName="direct_logs";
        channel.exchangeDeclare(exchangeName,"direct");

        String message="info: Hello world";
        String message1="warn: Hello world";
        String message2="error: Hello world";
        String message3="info: Hello world=============";
        channel.basicPublish(exchangeName,"info",null,message.getBytes());
        channel.basicPublish(exchangeName,"warn",null,message1.getBytes());
        channel.basicPublish(exchangeName,"error",null,message2.getBytes());
        channel.basicPublish(exchangeName,"info",null,message3.getBytes());


        channel.close();
        connection.close();

    }

}
public class Recv1 {
    public static void main(String[] args) throws Exception {
        final Connection connection = RabbitmqUtil.getConnection();
        final Channel channel = RabbitmqUtil.getChannel();
        String exchangeName = "direct_logs";
        String queueName = "logs_queue1";
        channel.queueDeclare(queueName, false, false, false, null);
        channel.queueBind(queueName,exchangeName,"info");

        channel.basicConsume(queueName,false,new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
               String message=new String(body);
                System.out.println("消费者[1] 接收消息:"+message);
            }
        });

    }

}
public class Recv2 {
    public static void main(String[] args) throws Exception {
        final Connection connection = RabbitmqUtil.getConnection();
        final Channel channel = RabbitmqUtil.getChannel();
        String exchangeName = "direct_logs";
        String queueName = "logs_queue2";
        channel.queueDeclare(queueName, false, false, false, null);
        channel.queueBind(queueName,exchangeName,"info");
        channel.queueBind(queueName,exchangeName,"warn");
        channel.queueBind(queueName,exchangeName,"error");

        channel.basicConsume(queueName,false,new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
               String message=new String(body);
                System.out.println("消费者[2] 接收消息:"+message);
            }
        });
      /*  channel.close();
        connection.close();*/

    }

}

执行结果

在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值