RabbbitMq入门以及四种队列模式

一、RabbitMq介绍

RabbitMQ是由erlang语言开发,基于AMQP(Advanced Message Queue 高级消息队列协议)协议实现的消息队列,它是一种应用程序之间的通信方法,消息队列在分布式系统开发中应用非常广泛。

问题来了,什么是消息队列?

MQ全称为Message Queue,即消息队列。“消息队列”是在消息的传输过程中保存消息的容器。它是典型的:生产者、消费者模型。生产者不断向消息队列中生产消息,消费者不断的从队列中获取消息。因为消息的生产和消费都是异步的,而且只关心消息的发送和接收,没有业务逻辑的侵入,这样就实现了生产者和消费者的解耦。

消息队列可以解决哪些问题?

使用消息队列,异步处理请求,将不必同步处理且耗时的操作,交由消息队列,并通知消息接收方进行异步处理,减少了应用程序的响应时间。解决高并发环境下,大量的同步请求堵塞。

生产方通过MQ与消费方交互,不必在服务器内部提供接口,解耦应用程序。

主流的MQ实现方式:AMQP、JMS

  • JMS是定义了统一的接口,来对消息操作进行统一;AMQP是通过规定协议来统一数据交互的格式

  • JMS限定了必须使用Java语言;AMQP只是协议,不规定实现方式,因此是跨语言的。

  • JMS规定了两种消息模型;而AMQP的消息模型更加丰富

 代表产品:ActiveMQ:基于JMS ;RabbitMQ:基于AMQP协议;

 RabbitMQ工作原理

RabbbitMq入门以及四种队列模式_第1张图片

 组成部分:

  •  Broker:消息队列服务进程,此进程包括两个部分:Exchange和Queue
  • Exchange:消息队列交换机,按一定的规则将消息路由转发到某个队列,对消息进行过虑。
  • Queue:消息队列,存储消息的队列,消息到达队列并转发给指定的
  • Producer:消息生产者,即生产方客户端,生产方客户端将消息发送
  • Consumer:消息消费者,即消费方客户端,接收MQ转发的消息。

二、四种常见的队列模式 

1、direct模式(直接模式)

 生产者将消息发送到交换器;队列根据routing_key接收消息,消费者消费queue接收到的消息。生产者也可以直接将消息发送给queue,而不设定Exchange以及路由键;

2、fanout模式(广播)

生产者将消息发送到交换器;队列接收所有消息,消费者消费指定queue接收到的消息;

3、topic模式 (匹配 订阅)

生产者将消息发送到交换器;队列根据routing_key接收消息,没有对应的routing_key则消息丢失;消费者消费queue接收到的消息;

4、header模式 (匹配)

生产者将带有header消息发送到交换器;队列根据交换机接收消息,并根据header消息与队列匹配;消费者消费queue接收到的消息;

三、队列模式的案例小实现

1、direct

简要说一下,rabbitmq安装在阿里云服务器docker容器中的连接问题:

需要在阿里云安全组里配置5672/15672端口   并且在容器中安装rabbitmq的需要对5672以及15672端口映射,这样外访的浏览器才可以通过映射的端口访问到docker容器中rabbitmq。

docker安装rabbitmq配置端口的示例:

docker run -d --hostname my-rabbit --name some-rabbit -p 8080:15672 -p 5672:5672 rabbitmq:3-management

浏览器登录web界面:http://ip地址:8080/

idea中配置连接:用5672端口   并且需要web页面里新添加一个root用户,tag为administrator,virtual-host设置为 /

原因是:默认的guest用户,只允许loclhost的地址访问,不允许外访 

RabbbitMq入门以及四种队列模式_第2张图片 

spring.rabbitmq.host=ip地址
spring.rabbitmq.port=5672
spring.rabbitmq.username=root
spring.rabbitmq.password=root
spring.rabbitmq.virtual-host=/

配置消息队列与交换机 

@Configuration
public class DirectConfig {
    //消息队列
    @Bean
    public Queue directQueue(){
        return new Queue("soul_direct");
    }
    //交换机
    @Bean
    public DirectExchange directExchange(){
        return new DirectExchange("soul_directExchange",true,false);
    }

    //队列绑定
    @Bean
    public Binding directBinding(){
        return  BindingBuilder.bind(directQueue()).to(directExchange()).with("soul_direct_routingKey");
    }

}

消息接收  

@Component
public class MessageReceive {
    @RabbitListener(queues = "soul_direct")
    public void directReceive(String mes){
        System.out.println("\n");
        System.out.println("\n");
        System.out.println("mes=" +mes);
        System.out.println("\n");
        System.out.println("\n");
    }
}

测试:

 @Autowired
    RabbitTemplate rabbitTemplate;
    @Test
    void contextLoads() {
        //直接发给队列
        rabbitTemplate.convertAndSend("soul_direct","hello! direct");
    }


@Test
    void test1() {
        //交给交换机路由给队列
     rabbitTemplate.convertAndSend("soul_directExchange","soul_direct_routingKey","hello! direct1");
    }



//测试结果:

 mes=hello! direct


-------------------------------------------------

mes=hello! direct1

2、fanout模式(广播到两个队列输出)

@Configuration
public class FanoutConfig {
    //队列
    @Bean
    public Queue fanoutQueueOne(){
        return new Queue("fanout_queueOne");
    }

    @Bean
    public Queue fanoutQueueTwo(){
        return new Queue("fanout_queueTwo");
    }
    //交换机
    @Bean
    public FanoutExchange fanoutExchange(){
        return new FanoutExchange("soul_fanoutExchange",true,false);
    }

    //队列绑定交换机  不需要添加路由键
    @Bean
    public Binding bindingOne(){
        return  BindingBuilder.bind(fanoutQueueOne()).to(fanoutExchange());
    }
    @Bean
    public Binding bindingTwo(){
        return  BindingBuilder.bind(fanoutQueueTwo()).to(fanoutExchange());
    }


}
@RabbitListener(queues = "fanout_queueOne")
    public void fanoutReceiveOne(String mes){
        System.out.println("\n");
        System.out.println("\n");
        System.out.println("fanout_queueOne:mes=" +mes);
        System.out.println("\n");
        System.out.println("\n");
    }

    @RabbitListener(queues = "fanout_queueTwo")
    public void fanoutReceiveTwo(String mes){
        System.out.println("\n");
        System.out.println("\n");
        System.out.println("fanout_queueTwo:mes=" +mes);
        System.out.println("\n");
        System.out.println("\n");
    }

测试:

@Test
    void test2() {
        //交给交换机处理
        rabbitTemplate.convertAndSend("soul_fanoutExchange",null,"Live like a dog");
    }



//测试结果

fanout_queueTwo:mes=Live like a dog

fanout_queueOne:mes=Live like a dog

3、topic(订阅 匹配)

@Configuration
public class TopicConfig {
    @Bean
    public Queue queue1(){
        return new Queue("dog1");
    }

    @Bean
    public Queue queue2(){
        return new Queue("dog2");
    }

    @Bean
    public Queue queue3(){
        return new Queue("dog3");
    }
    @Bean
    public TopicExchange topicExchange(){
        return new TopicExchange("soul_topicExchange");
    }

    @Bean
    public Binding binding(){
        return BindingBuilder.bind(queue1()).to(topicExchange()).with("dog1.#");
    }

    @Bean
    public Binding binding1(){
        return BindingBuilder.bind(queue2()).to(topicExchange()).with("dog2.#");
    }

    @Bean
    public Binding binding2(){
        return BindingBuilder.bind(queue3()).to(topicExchange()).with("#.dog3.#");
    }
}
@RabbitListener(queues = "dog1")
    public void topic1(String mes){
        System.out.println("dog1:mes=" +mes);
    }

    @RabbitListener(queues = "dog2")
    public void topic2(String mes){
        System.out.println("dog2:mes=" +mes);
    }

    @RabbitListener(queues = "dog3")
    public void topic3(String mes){
        System.out.println("dog3:mes=" +mes);
    }

测试:

 @Test
    void test3() {
        //交给交换机处理
        rabbitTemplate.convertAndSend("soul_topicExchange","dog1.dog3","Live like a dog");
    }


//结果

dog3:mes=Live like a dog
dog1:mes=Live like a dog

4、header

@Configuration
public class HeaderConfig {


    @Bean
    HeadersExchange headersExchange() {
        return new HeadersExchange("soul_headersExchange", true, false);
    }

    @Bean
    Queue queueName() {
        return new Queue("name-queue");
    }

    @Bean
    Queue queueAge() {
        return new Queue("age-queue");
    }

    @Bean
    Binding bindingName() {
        Map map = new HashMap<>();
        map.put("name", "Live like a dog");
        return BindingBuilder.bind(queueName()).to(headersExchange()).whereAny(map).match();
    }
    //whereAny和where是用来匹配的
    @Bean
    Binding bindingAge() {
        return BindingBuilder.bind(queueAge()).to(headersExchange()).where("age").exists();
    }
}
 @RabbitListener(queues = "name-queue")
    public void header1(String mes){
        System.out.println("name-queue:mes=" +mes);
    }

    @RabbitListener(queues = "age-queue")
    public void header2(String mes){
        System.out.println("age-queue:mes=" +mes);
    }

测试:

  @Test
    void test4() {
       Message message = MessageBuilder.withBody("Live like a dog".getBytes()).setHeader("name","Live like a dog").build();
        //交给交换机处理
        rabbitTemplate.convertAndSend("soul_headersExchange","dog1.dog3",message);
    }


//结果:
 

name-queue:mes=Live like a dog

你可能感兴趣的:(笔记,rabbitmq)