1.RabbitMQ

是实现了高级消息队列协议(AMQP)的开源消息代理软件(亦称面向消息的中间件)。

2.RabbitMQ应用场景

 跨系统的异步通信,所有需要异步交互的地方都可以使用消息队列。就像我们除了打电话(同步)以外,还需要发短信,发电子邮件(异步)的通讯方式。

流量削峰一般在秒杀活动中应用广泛。

3.rabbitmq 有哪些重要的角色?

RabbitMQ 中重要的角色有:生产者、消费者和代理:

生产者:消息的创建者,负责创建和推送数据到消息服务器;
消费者:消息的接收方,用于处理数据和确认消息;
代理:就是 RabbitMQ 本身,用于扮演“快递”的角色,本身不生产消息,只是扮演“快递”的角色。

4.rabbitmq 有哪些重要的组件?

ConnectionFactory(连接管理器):应用程序与Rabbit之间建立连接的管理器,程序代码中使用。
Channel(信道):消息推送使用的通道。我们必须连接Rabbit服务,才能消费或者发布消息,
Exchange(交换器):用于接受、分配消息。
Queue(队列):用于存储生产者的消息。
RoutingKey(路由键):用于把生成者的数据分配到交换器上。
BindingKey(绑定键):用于把交换器的消息绑定到队列上。

5.rabbitmq的常见工作模式

  • fanout
  • direct
  • topic
  • headers

 普通模式

一个队列只有一个消费者,生产者将消息发送到队列,消费者从队列中取出消息

Fanout Exchange:直接将消息转发到所有binding的对应queue中,这种exchange在路由转发的时候,忽略Routing key。

 订阅模式

一个交换机绑定多个消息队列,每个消息队列有一个消费者监听,生产者发送的消息可以被每一个消费者接收

Direct Exchange:将消息中的Routing key与该Exchange关联的所有Binding中的Routing key进行比较,如果相等,则发送到该Binding对应的Queue中。

路由模式

一个交换机绑定多个消息队列,每个消息队列都有自己唯一的key,每一个消息队列有一个消费者监听

Topic Exchange:将消息中的Routing key与该Exchange关联的所有Binding中的Routing key进行对比,如果匹配上了,则发送到该Binding对应的Queue中。

Headers Exchange:将消息中的headers与该Exchange相关联的所有Binging中的参数进行匹配,如果匹配上了,则发送到该Binding对应的Queue中。

6.参数详解

Virtual host:属于哪个Virtual host。

Name:名字,同一个Virtual host里面的Name不能重复。

Durability: 是否持久化,Durable:持久化。Transient:不持久化。

Auto delete:当最后一个绑定(队列或者exchange)被unbind之后,该exchange自动被删除。

Internal: 是否是内部专用exchange,是的话,就意味着我们不能往该exchange里面发消息。

Arguments: 参数,是AMQP协议留给AMQP实现做扩展使用的。
alternate_exchange配置的时候,exchange根据路由路由不到对应的队列的时候,这时候消息被路由到指定的alternate_exchange的value值配置的exchange上

Virtual host

 

 7.Spring对RabbitMQ的整合

    <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-amqp</artifactId>
      </dependency>

 application.yaml

spring:
  rabbitmq:
    host: 101.200.72.***
    username: hdh
    password: ******
    port: 5672
    virtual-host: /msg
   template:
     retry:
       #重试开启
       enabled: true
       #10秒后重试
       initial-interval: 10000ms
       #最大的重试周期
       max-interval: 30000ms
       #重试周期倍数  initial-interval*multiplier
       multiplier: 2
       #默认的交换机的名称(不写使用默认的)
     exchange:
       #开启生产者消息发送失败重试
    publisher-confirms: true

如何发送消息到队列或者交换机

     @Autowired
     private AmqpTemplate amqpTemplate;
String msg
="hello spring boot mq"; //向交换机或者队列发送消息 队列、交换机必须存在 this.amqpTemplate.convertAndSend("spring.MQ.queue","a.b",msg);

如何处理消息

不需要创建RabbitMQ的消息队列

@Component
public class StatementQueueExchangeCopy {

    @RabbitListener(queues = "spring.MQ.queue")
    private void listen(String msg) {

        System.out.println("[接受消息]" + msg);

    }
}

需要在程序启动的时候创建RabbitMQ的消息队列

@Component
//程序运行时创建好队列
public class StatementQueueExchange {
    @RabbitListener(bindings = @QueueBinding(
            //创建队列spring.MQ.queue  默认持久化
            value = @Queue(value = "spring.MQ.queue", declare = "true"),
            //创建交换机spring.MQ.exchange
            exchange = @Exchange(
                    value = "spring.MQ.exchange",
                    type = ExchangeTypes.TOPIC
            ),
            //绑定规则
            key = {"#.#"}
    ))
    private void listen(String msg) {

        System.out.println("[接受消息]" + msg);

    }
}

Spring默认开启了消息持久化

 8.手写一个RabbitMQ消息的生产和消费

消息生产

public class Send {

    private final static String EXCHANGE_NAME = "durable_exchange";

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

        //获取到连接
        Connection connection = ConnectionUtils.getConnection();

        //获取通道
        Channel channel = connection.createChannel();

        //声明exchange,指定类型fanout     交换机持久化
        channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.FANOUT, true);

        String message = "helle everyone";
        //发布消息到exchange交换机
        for (int i = 1; i < 100; i++) {
            channel.basicPublish(EXCHANGE_NAME, "", MessageProperties.PERSISTENT_TEXT_PLAIN, message.getBytes());
            System.out.println("生产者send:" + message);
        }
        channel.close();
        connection.close();

    }
}

消息消费

public class Receive {

    private final static String EXCHANGE_NAME = "durable_exchange";
    private final static String QUERY_NAME = "durable";

    public static void main(String[] args) throws IOException, TimeoutException {
        //获取连接
        Connection connection = ConnectionUtils.getConnection();
        //获取通道
        Channel channel = connection.createChannel();
        //获取队列  队列持久化
        channel.queueDeclare(QUERY_NAME, true, false, false, null);

        //将队列和交换机绑定
        channel.queueBind(QUERY_NAME, EXCHANGE_NAME, "");

        //定义对队列的消费者
        DefaultConsumer consumer = new DefaultConsumer(channel) {
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                String msg = new String(body);
                System.out.println("消费者1:" + msg);
            }
        };
        //ack确认机制
        channel.basicConsume(QUERY_NAME, true, consumer);

    }
}

 

 

 

 

 

 

 

 

 

posted on 2020-09-26 17:24  忆夏KhaZix  阅读(125)  评论(0编辑  收藏  举报