RabbitMQ第二章

RabbitMQ多种模式:

  • Work queues (工作模式):
    在这里插入图片描述
    代码实践:
public class Produce01 {  // 工作模式 生产者

    //队列名
    private static final String QUEUE = "SERVER_A";

    public static void main(String[] args) {
        //生产者通过会话通道将信息发送至MQ服务然后由路由器将消息转发至队列中

        //创建连接工厂
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("127.0.0.1"); //连接地址
        factory.setPort(5672); //端口
        factory.setUsername("guest");
        factory.setPassword("guest");
        //设置虚拟机  每个虚拟机相当于独立的MQ
        factory.setVirtualHost("/");

        Connection connection = null;
        Channel channel = null;

        try {
            //建立连接
            connection = factory.newConnection();
            //创建会话通道  生产者和MQ服务的通信都在通道中完成
            channel = connection.createChannel();
            /**
             * 声明队列  如队列不存在则创建队列
             * 队列参数
             * String queue, 队列名
             * boolean durable, 持久化
             * boolean exclusive, 是否独占队列  队列只允许当前连接访问 连接关闭队列删除  true 代表临时队列
             * boolean autoDelete, 是否自动删除  exclusive设置为临时队列(true) 那么连接关闭队列自动删除
             * Map<String, Object> arguments 扩展参数  例如 队列存活时间
             */
            channel.queueDeclare(QUEUE,true,false,false,null);
            /**
             * 发送消息
             * String exchange, 交换机  如设定交换机则使用mq默认交换机
             * String routingKey, 路由key 交换机根据路由key将消息转发到指定的队列中,默认交换机则设置队列的名
             * BasicProperties props, 消息属性
             * byte[] body 消息体
             */
            String message = "Hello RabbitMQ"; //消息内容
            channel.basicPublish("",QUEUE,null,message.getBytes());
            System.out.println("produce send mq:" + message);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {

            try {
                channel.close(); //关闭会话通道
            } catch (IOException e) {
                e.printStackTrace();
            } catch (TimeoutException e) {
                e.printStackTrace();
            }

            try {
                connection.close(); //关闭连接
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

}
public class Consumer01 { //消费者

    private static final String QUEUE = "SERVER_A";

    public static void main(String[] args) {
        //创建连接工厂
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("127.0.0.1"); //连接地址
        factory.setPort(5672); //端口
        factory.setUsername("guest");
        factory.setPassword("guest");
        factory.setVirtualHost("/"); //设置虚拟机
        Connection connection = null;
        try {
            connection = factory.newConnection(); //建立连接
            Channel channel = connection.createChannel(); //创建会话通道
            /** 监听哪个队列
             * 声明队列  如队列不存在则创建队列
             * 队列参数
             * String queue, 队列名
             * boolean durable, 持久化
             * boolean exclusive, 是否独占队列  队列只允许当前连接访问 连接关闭队列删除  true 代表临时队列
             * boolean autoDelete, 是否自动删除  exclusive设置为临时队列(true) 那么连接关闭队列自动删除
             * Map<String, Object> arguments 扩展参数  例如 队列存活时间
             */
            channel.queueDeclare(QUEUE,true,false,false,null);

            //实现消费方法
            DefaultConsumer defaultConsumer = new DefaultConsumer(channel){
                /**
                 * 当接受到消息此方法就会执行消费
                 * @param consumerTag  消费者标签  标识消费者
                 * @param envelope 信封
                 * @param properties 消息属性
                 * @param body 消息体
                 * @throws IOException
                 */
                @Override
                public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                    String exchange = envelope.getExchange(); //交换机
                    long deliveryTag = envelope.getDeliveryTag(); //消息ID
                    String message = new String(body,"UTF-8");
                    System.out.println("consumer :" + message);
                }
            };


            /**
             * 开始监听队列
             * String queue, 队列名
             * DeliverCallback deliverCallback, true 自动回复MQ消息已接收
             * CancelCallback cancelCallback
             */
            channel.basicConsume(QUEUE,true,defaultConsumer);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (TimeoutException e) {
            e.printStackTrace();
        }
    }

}

一个生产者将消息发送给一个队列,多个消费者共同监听这个队列,rabbitmq采用轮询方式将消息平均发送给消费者。

  • Publish/Subscribe(发布订阅模式):
    在这里插入图片描述

代码实践:

public class Produce_publish { //广播模式   生产者

    private static final String QUEUE_SMS = "queue_inform_sms"; //短信队列名

    private static final String QUEUE_EMAIL = "queue_inform_email"; //邮件队列名

    private static final String EXCHANGE_FANOUT_INFORM = "exchange_fanout_inform"; //交换机

    public static void main(String[] args) {
        //创建连接工厂
        ConnectionFactory factory = new ConnectionFactory();
        factory.setPort(5672);
        factory.setHost("127.0.0.1");
        factory.setUsername("guest");
        factory.setPassword("guest");
        factory.setVirtualHost("/");
        Connection connection = null;
        Channel channel = null;
        try {
            //建立连接
            connection = factory.newConnection();
            channel = connection.createChannel();//创建会话通道
            //短信队列
            channel.queueDeclare(QUEUE_SMS,true,false,false,null);
            //邮件队列
            channel.queueDeclare(QUEUE_EMAIL,true,false,false,null);
            /**
             * 声明交换机
             * String exchange,
             * BuiltinExchangeType type:
             *          BuiltinExchangeType.FANOUT  对应发布订阅模式
             *          BuiltinExchangeType.DIRECT 对应路由模式
             *          BuiltinExchangeType.TOPIC 对应通配符模式
             *          BuiltinExchangeType.HEADERS 对应转发器模式
             */
            channel.exchangeDeclare(EXCHANGE_FANOUT_INFORM, BuiltinExchangeType.FANOUT);
            /**
             * 交换机与队列进行绑定
             * String queue, 队名名
             * String exchange, 交换机名
             * String routingKey 路由key  交换机根据路由key将消息转发到指定的队列中
             */
            channel.queueBind(QUEUE_SMS,EXCHANGE_FANOUT_INFORM,"");
            channel.queueBind(QUEUE_EMAIL,EXCHANGE_FANOUT_INFORM,"");

            for (int i = 0;i<5;i++){
                String message = "rabbitmq send 发布订阅模式...";
                /**
                 * String exchange,
                 * String routingKey,
                 * BasicProperties props,
                 * byte[] body
                 */
                channel.basicPublish(EXCHANGE_FANOUT_INFORM,"",null,message.getBytes());
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                channel.close();
                connection.close();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (TimeoutException e) {
                e.printStackTrace();
            }
        }
    }
}
public class Consumer_Email { //邮箱队列

    private static final String QUEUE_EMAIL = "queue_inform_email"; //邮件队列名
    private static final String EXCHANGE_FANOUT_INFORM = "exchange_fanout_inform"; //交换机

    public static void main(String[] args) {

        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("127.0.0.1");
        factory.setPort(5672);
        factory.setUsername("guest");
        factory.setPassword("guest");
        factory.setVirtualHost("/");

        Connection connection = null;
        Channel channel = null;
        try {
            //建立连接
            connection = factory.newConnection();
            //建立通道
            channel = connection.createChannel();
            //监听通道
            channel.queueDeclare(QUEUE_EMAIL,true,false,false,null);
            //声明交换机
            channel.exchangeDeclare(EXCHANGE_FANOUT_INFORM, BuiltinExchangeType.FANOUT);
            //绑定队列与交换机
            channel.queueBind(QUEUE_EMAIL,EXCHANGE_FANOUT_INFORM,"");


            DefaultConsumer consumer = new DefaultConsumer(channel){
                @Override
                public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                    String exchange = envelope.getExchange(); //交换机
                    String routingKey = envelope.getRoutingKey(); //routingKey
                    long deliveryTag = envelope.getDeliveryTag(); //消息ID
                    String message = new String(body,"UTF-8");
                    System.out.println("Consumer Email message:" + message);
                }
            };
            channel.basicConsume(QUEUE_EMAIL,true,consumer);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
public class Consumer_SMS { //短信队列

    private static final String QUEUE_SMS = "queue_inform_sms"; //短信队列名

    private static final String EXCHANGE_FANOUT_INFORM = "exchange_fanout_inform"; //交换机

    public static void main(String[] args) {
        //创建连接工厂
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("127.0.0.1"); //连接地址
        factory.setPort(5672); //端口
        factory.setUsername("guest");
        factory.setPassword("guest");
        factory.setVirtualHost("/"); //设置虚拟机
        Connection connection = null;
        try {
            connection = factory.newConnection(); //建立连接
            Channel channel = connection.createChannel(); //创建会话通道
            /** 监听哪个队列
             * 声明队列  如队列不存在则创建队列
             * 队列参数
             * String queue, 队列名
             * boolean durable, 持久化
             * boolean exclusive, 是否独占队列  队列只允许当前连接访问 连接关闭队列删除  true 代表临时队列
             * boolean autoDelete, 是否自动删除  exclusive设置为临时队列(true) 那么连接关闭队列自动删除
             * Map<String, Object> arguments 扩展参数  例如 队列存活时间
             */
            channel.queueDeclare(QUEUE_SMS,true,false,false,null);

            channel.exchangeDeclare(EXCHANGE_FANOUT_INFORM,BuiltinExchangeType.FANOUT);
            channel.queueBind(QUEUE_SMS,EXCHANGE_FANOUT_INFORM,"");


            /**
             * 开始监听队列
             * String queue, 队列名
             * DeliverCallback deliverCallback, true 自动回复MQ消息已接收
             * CancelCallback cancelCallback
             */
            Consumer defaultConsumer = new DefaultConsumer(channel){
                @Override
                public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                    String exchange = envelope.getExchange(); //交换机
                    long deliveryTag = envelope.getDeliveryTag(); //消息ID
                    String message = new String(body,"UTF-8");
                    System.out.println("consumer :" + message);
                }
            };
            channel.basicConsume(QUEUE_SMS,true,defaultConsumer);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

生产者将消息发送给交换机,由交换机将消息转发到与交换机绑定的多个队列上,每个消费者监听自己的队列。
注意:如果生产者发送多条信息至队列,多个消费者同时监听一个队列就会出现消息重复消费问题!

发布了19 篇原创文章 · 获赞 8 · 访问量 807

猜你喜欢

转载自blog.csdn.net/ysl_20190905/article/details/100715111