RabbitMQ-基础(二)

个人笔记

目录

交换机

Direct Exchange(直连交换机):

Fanout Exchange(扇型交换机,又称广播交换机)

Topic Exchange(主题交换机)

Headers Exchange(头交换机)


交换机

 

RabbitMQ的交换机类型共有四种,是根据其路由过程的不同而划分成的

分别是Direct Exchange(直连交换机), Fanout Exchange(扇型交换机,又称广播交换机), Topic Exchange(主题交换机)与 Headers Exchange(头交换机)

Direct Exchange(直连交换机):

                                                                            

在该图中,直连交换器X上绑定了两个队列。第一个队列绑定了绑定键orange,第二个队列有两个绑定键:black和green。在这种场景下,一个消息在布时指定了路由键为orange将会只被路由到队列Q1,路由键为black和green的消息都将被路由到队列Q2。其他的消息都将被丢失。

                                                                            

同一个绑定键可以绑定到不同的队列上去,在上图中,我们也可以增加一个交换器X与队列Q2的绑定键,在这种情况下,直连交换器将会和广播交换器有着相同的行为,将消息推送到所有匹配的队列。一个路由键为black的消息将会同时被推送到队列Q1和Q2。

发送者:

public class MqDirectSendHandler {


    protected static final String QUEUE_NAME = "queue.hello";
    protected static final String ROUTE_KEY_ONE = "route.key.hello1";
    protected static final String ROUTE_KEY_TWO = "route.key.hello2";
    protected static final String ROUTE_KEY_THREE = "route.key.hello3";

    protected static final String EXCHANGE_NAME = "direct.hello";


    public static void main(String[] args) throws IOException {
        directExchangeMoreQueueSend();
    }



    public static void directExchangeMoreQueueSend() throws IOException {
        Channel channel = MqConnectionUtils.getChannel();
        channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.DIRECT);
        String message = "hello world ";
        for (int i = 0; i < 10; i++) {
            String x = message;
            String y = message;
            String z = message;
            x = "Route one " + x + i;
            y = "Route two " + y + i;
            z = "Route three " + z + i;
            channel.basicPublish(EXCHANGE_NAME, ROUTE_KEY_ONE,         MessageProperties.MINIMAL_BASIC, x.getBytes(StandardCharsets.UTF_8));
            channel.basicPublish(EXCHANGE_NAME, ROUTE_KEY_THREE, MessageProperties.MINIMAL_BASIC, z.getBytes(StandardCharsets.UTF_8));
            channel.basicPublish(EXCHANGE_NAME, ROUTE_KEY_TWO, MessageProperties.MINIMAL_BASIC, y.getBytes(StandardCharsets.UTF_8));
        }
        System.out.println("end");
    }

}

消费者:

public class MqDirectRecHandler {

    protected static final String ROUTE_KEY_ONE = "route.key.hello1";
    protected static final String ROUTE_KEY_TWO = "route.key.hello2";
    protected static final String ROUTE_KEY_THREE = "route.key.hello3";

    protected static final String EXCHANGE_NAME = "direct.hello";


    public static void main(String[] args) throws IOException {

        directRecBindMoreQueueRec();
    }


    public static void directRecBindMoreQueueRec() throws IOException {
        Channel channel = MqConnectionUtils.getChannel();
        channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.DIRECT);

        String queue = channel.queueDeclare().getQueue();
        channel.queueBind(queue,EXCHANGE_NAME,ROUTE_KEY_ONE);
        channel.queueBind(queue,EXCHANGE_NAME,ROUTE_KEY_THREE);
        channel.queueBind(queue,EXCHANGE_NAME,ROUTE_KEY_TWO);
        DeliverCallback deliverCallback = (consumerTag, deliver) -> {
            String message = new String(deliver.getBody(), StandardCharsets.UTF_8);
            System.out.println("Direct监听者多队列绑定队列:" + message);
        };
        channel.basicConsume(queue, Boolean.TRUE, deliverCallback, consumerTag -> {
        });
    }

}

Fanout Exchange(扇型交换机,又称广播交换机)

                                                                         

生产者把消息发送到交换机后,由交换机发送给消费者队列。消费者队列如果想要接收到交换机里的消息,那么需要保证:队列绑定的交换机名称要和交换机一致,这个是广播模式的关键,路由key可以忽略,也是MQ后续所有模式最粗略的前提。

发送者:

public class MqFanoutSendHandler {


    protected static final String QUEUE_NAME = "queue.hello";


    protected static final String EXCHANGE_NAME_ONE = "fanout.hello1";



    public static void main(String[] args) throws IOException {
        fanoutExchangeQueueSend();
    }

    public static void fanoutExchangeQueueSend() throws IOException {
        Channel channel = MqConnectionUtils.getChannel();
        channel.exchangeDeclare(EXCHANGE_NAME_ONE, BuiltinExchangeType.FANOUT, Boolean.FALSE, Boolean.TRUE, null);
        channel.exchangeDeclare(EXCHANGE_NAME_TWO, BuiltinExchangeType.FANOUT, Boolean.FALSE, Boolean.TRUE, null);
        String message = "hello world ";
        for (int i = 0; i < 10; i++) {
            String x = message;
            String y = message;
            x = "交换机1:" + x + i;
            y = "交换机2:" + y + i;
            channel.basicPublish(EXCHANGE_NAME_ONE, "", MessageProperties.MINIMAL_BASIC, x.getBytes(StandardCharsets.UTF_8));

            channel.basicPublish(EXCHANGE_NAME_TWO, "", MessageProperties.MINIMAL_BASIC, y.getBytes(StandardCharsets.UTF_8));
        }
        System.out.println("end");
    }


}

消费者:

public class MqFanoutRecHandler {

    protected static final String QUEUE_NAME = "queue.hello";

    protected static final String EXCHANGE_NAME_ONE = "fanout.hello1";
    protected static final String EXCHANGE_NAME_TWO = "fanout.hello2";

    public static void main(String[] args) throws IOException {
        fanoutOnlyRecBindQueueRec();
    }

    public static void fanoutOnlyRecBindQueueRec() throws IOException {
        Channel channel = MqConnectionUtils.getChannel();
        channel.exchangeDeclare(EXCHANGE_NAME_ONE, BuiltinExchangeType.FANOUT,Boolean.FALSE,Boolean.TRUE,null);
        channel.exchangeDeclare(EXCHANGE_NAME_TWO, BuiltinExchangeType.FANOUT,Boolean.FALSE,Boolean.TRUE,null);
        channel.queueDeclare(QUEUE_NAME,Boolean.FALSE,Boolean.FALSE,Boolean.TRUE,null);
        channel.queueBind(QUEUE_NAME,EXCHANGE_NAME_ONE,"");
        channel.queueBind(QUEUE_NAME,EXCHANGE_NAME_TWO,"");
        DeliverCallback deliverCallback = (consumerTag, deliver) -> {
            String message = new String(deliver.getBody(), StandardCharsets.UTF_8);
            System.out.println("Fanout听风者:" + message);
        };
        channel.basicConsume(QUEUE_NAME, Boolean.TRUE,deliverCallback,consumerTag->{});
    }
}

Topic Exchange(主题交换机)

                                                                     

主体模式其实就是在路由模式的基础上,支持了对key的通配符匹配(*号以及#号),以满足更加复杂的消息分发场景(“#” : 匹配一个或者多个字符,“*”:匹配一个字符)。


发送者:

public class MqTopicSendHandler {

    protected static final String QUEUE_NAME = "topic.queue.hello";
    protected static final String ROUTE_KEY_ONE = "quick.orange.rabbit";
    protected static final String ROUTE_KEY_TWO = "lazy.orange.elephant";
    protected static final String ROUTE_KEY_THREE = "quick.orange.fox";
    protected static final String ROUTE_KEY_FOUR = "lazy.brown.fox";
    protected static final String ROUTE_KEY_FIVE = "lazy.pink.rabbit";
    protected static final String ROUTE_KEY_SIX = "quick.brown.fox";
    protected static final String ROUTE_KEY_SEVEN = "大西瓜";

    protected static final String EXCHANGE_NAME = "topic.hello";

    public static void main(String[] args) throws IOException {
        topicExchangeQueueSend();
    }


    public static void topicExchangeQueueSend() throws IOException {
        Channel channel = MqConnectionUtils.getChannel();
        channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.TOPIC, Boolean.FALSE,Boolean.TRUE,null);
        String message = "hello world ";
        for (int i = 0; i < 10; i++) {
            channel.basicPublish(EXCHANGE_NAME, ROUTE_KEY_ONE, MessageProperties.MINIMAL_BASIC, (ROUTE_KEY_ONE + " " + message + i).getBytes(StandardCharsets.UTF_8));
            channel.basicPublish(EXCHANGE_NAME, ROUTE_KEY_TWO, MessageProperties.MINIMAL_BASIC, (ROUTE_KEY_TWO + " " + message + i).getBytes(StandardCharsets.UTF_8));
            channel.basicPublish(EXCHANGE_NAME, ROUTE_KEY_THREE, MessageProperties.MINIMAL_BASIC, (ROUTE_KEY_THREE + " " + message + i).getBytes(StandardCharsets.UTF_8));
            channel.basicPublish(EXCHANGE_NAME, ROUTE_KEY_FOUR, MessageProperties.MINIMAL_BASIC, (ROUTE_KEY_FOUR + " " + message + i).getBytes(StandardCharsets.UTF_8));
            channel.basicPublish(EXCHANGE_NAME, ROUTE_KEY_FIVE, MessageProperties.MINIMAL_BASIC, (ROUTE_KEY_FIVE + " " + message + i).getBytes(StandardCharsets.UTF_8));
            channel.basicPublish(EXCHANGE_NAME, ROUTE_KEY_SIX, MessageProperties.MINIMAL_BASIC, (ROUTE_KEY_SIX + " " + message + i).getBytes(StandardCharsets.UTF_8));
            channel.basicPublish(EXCHANGE_NAME, ROUTE_KEY_SEVEN, MessageProperties.MINIMAL_BASIC, (ROUTE_KEY_SEVEN + " " + message + i).getBytes(StandardCharsets.UTF_8));
        }
        System.out.println("end");
    }
}

消费者:

public class MqTopicRecHandler {


    protected static final String QUEUE_NAME = "topic.queue.hello";
    protected static final String ROUTE_KEY_TOPIC_ONE = "#.rabbit";
    protected static final String ROUTE_KEY_TOPIC_TWO = "*.orange.rabbit";
    protected static final String ROUTE_KEY_TOPIC_THREE = "#.orange.*";
    protected static final String ROUTE_KEY_TOPIC_FOUR = "#";
    protected static final String EXCHANGE_NAME = "topic.hello";

    public static void main(String[] args) throws IOException {
        topicRecBindQueueRec();
    }


    public static void topicRecBindQueueRec() throws IOException {
        Channel channel = MqConnectionUtils.getChannel();
        channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.TOPIC, Boolean.FALSE, Boolean.TRUE, null);
        channel.queueDeclare(QUEUE_NAME, Boolean.FALSE, Boolean.FALSE, Boolean.TRUE, null);
        channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, ROUTE_KEY_TOPIC_TWO );
        DeliverCallback deliverCallback = (consumerTag, deliver) -> {
            String message = new String(deliver.getBody(), StandardCharsets.UTF_8);
            System.out.println(message);
        };
        channel.basicConsume(QUEUE_NAME, Boolean.TRUE, deliverCallback, consumerTag -> {
        });
    }

}

Headers Exchange(头交换机)

Headers类型的exchange使用的比较少,以至于官方文档貌似都没提到,它是忽略routingKey的一种路由方式。是使用Headers来匹配的。Headers是一个键值对,可以定义成Hashtable。发送者在发送的时候定义一些键值对,接收者也可以再绑定时候传入一些键值对,两者匹配的话,则对应的队列就可以收到消息。 

匹配有两种方式all和any。这两种方式是在接收端必须要用键值”x-mactch”来定义。all代表定义的多个键值对都要满足,any代表只要满足一个就可以。fanout,direct,topic exchange的routingKey都需要要字符串形式的,而headers exchange则没有这个要求,因为键值对的值可以是任何类型。

发送者:

public class MqHeaderSendHandler {

    protected static final String EXCHANGE_NAME = "header.hello";

    public static void main(String[] argv) throws Exception {

        String message = "hello world";


        Map<String, Object> headers = new HashMap<>(BaseConstant.SIX);

        headers.put("hello","world");

        try (Channel channel = MqConnectionUtils.getChannel()) {
            channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.HEADERS, Boolean.FALSE, Boolean.TRUE, null);
            AMQP.BasicProperties.Builder builder = new AMQP.BasicProperties.Builder();
            //传递方式
            builder.deliveryMode(MessageProperties.PERSISTENT_TEXT_PLAIN.getDeliveryMode());
            //优先级
            builder.priority(MessageProperties.PERSISTENT_TEXT_PLAIN.getPriority());
            builder.headers(headers);
            AMQP.BasicProperties props = builder.build();
            channel.basicPublish(EXCHANGE_NAME,"", props, message.getBytes(StandardCharsets.UTF_8));

        }
    }

}

消费者:

public class MqHeaderRecHandler {


    protected static final String EXCHANGE_NAME = "header.hello";
    protected static final String QUEUE_NAME = "header.queue.hello";

    public static void main(String[] argv) throws Exception {

        Channel channel = MqConnectionUtils.getChannel();

        channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.HEADERS, Boolean.FALSE, Boolean.TRUE, null);


        Map<String, Object> headers = new HashMap<>();
        headers.put("hello", "world");

        channel.queueDeclare(QUEUE_NAME, Boolean.FALSE, Boolean.FALSE, Boolean.TRUE, null);
        channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, "", headers);

        DeliverCallback deliverCallback = (consumerTag, delivery) -> {
            String message = new String(delivery.getBody(), StandardCharsets.UTF_8);
            System.out.println("接收消息"+ message);
        };
        channel.basicConsume(QUEUE_NAME, Boolean.TRUE, deliverCallback, consumerTag -> {
        });
    }
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值