RabbitMq大纲

一、AMQP协议模型

消息通过发布者,发到了Exchange上,Exchange在通过routeKey找到对应的Queue队列
1、注意里面包含【虚拟机 Virtual host】、【Exchange】、【routeKey】、【queue】
2、一个Exchange可以绑定多个routeKey,一个routeKey对应一个queue
3、Exchange必须是在同一个虚拟机【Virtual host】里面

二、保障消息百分百投递成功

1、首先在发消息前,将数据保存至业务表,然后再生成MSG,保存至消息表。状态为0,表示待发送。
2、然后开始发送,在消息成年发送到mq服务端,也就是MqBroker的时候,就会收到mqBroker的【消息确认回调】表示成功接收到消息了,也就是step3
3、收到确认消息,同事我们在更新MSG表中的发送状态,更新为已发送,也就是1
4、假设step3失败,也就是消息发送到服务端,但是回调消息在回来的时候断了,可能是因为网络断了什么的。
5、那么可以通过定时任务去跑MSG的表状态等于0的。
6、如果确认回调消息一直失败,也就没法更新MSG表的状态,那么就会一直发,消息到MqBroker,那么MqBroker就一直给消费端发消息,消息端一定要做好幂等,也就是相同消息过来处理结果都是一样的。
7、因为考虑到消息重复发送给MqBroker,必然会影响到其他消息进入到MqBroker,所以要在

三、代码

1、消息消费

//durable表示数据是否持久化
@RabbitListener(bindings = @QueueBinding(
value = @Queue(value = "order-queue",durable = "true"),
exchange = @Exchange(name = "order-exchange", durable = "true",type = "topic"),
key="order.*"))

@RabbitHandler
public void onOrderMessage(@Payload Order order, @Headers Map<String,Object> headers, Channel channel) throws Exception {
    System.out.println("----收到消息,开始消费-----");
    System.out.println("d订单id:"+order.getId());
    
    Long deliveryTag = (Long) headers.get(AmqpHeaders.DELIVERY_TAG);

    /**
     *  取值为 false 时,表示通知 RabbitMQ 当前消息被确认
     *  如果为 true,则额外将比第一个参数指定的 delivery tag 小的消息一并确认
     */
    channel.basicAck(deliveryTag,false);
    System.out.println("--------消费完成--------");
}

疑问:如果没有确认,那么下一条消息是什么时候过来。

spring:
  rabbitmq: #基本配置
    addresses: www.niezhiliang.com:5672  //mq服务端地址
    username: springcloud			
    password: 123456				
    virtual-host: /    #虚拟主机地址,不写表示所有,写了,就表示发送和接受只能在当前虚拟主机下的人可以收到。
    connection-timeout: 15000			链接超时时间。客户端链接服务点的超时时间。

    listener:  	#消费端配置
      simple:	#消费端
        concurrency: 5      默认五个线程,也就是相当于五个channel,就相当于默认有5个consume
        max-concurrency: 10		#最大消费端数
        acknowledge-mode: manual			#自动签收-auto  手动-manual,注意这是针对所有消费端,也就是说所有的消费端,都要手动确认,下面会介绍针对单个消费端。
        prefetch: 1				#限流(海量数据,同时只能过来一条)
spring:
  rabbitmq:
    publisher-confirms: true   开启投递确认模式,投递表示消息发送方,在发给MqServer成功收到消息后,MQserver会给发送方一个confirm回执,表示发送方的消息投递成功。
    publisher-returns: true
    template:
      mandatory: true
    overtime: 1 #重新投递时间(分钟)

2、消息发送代码、以及消息回调callBack

@Autowired
private RabbitTemplate rabbitTemplate;

//定义confirmCallBack函数

final RabbitTemplate.ConfirmCallback confirmCallback = new RabbitTemplate.ConfirmCallback() {

    /**
     *
     * @param correlationData 唯一标识,有了这个唯一标识,我们就知道可以确认(失败)哪一条消息了
     * @param ack  是否投递成功
     * @param cause 失败原因
     */
    @Override
    public void confirm(CorrelationData correlationData, boolean ack, String cause) {
        String messageId = correlationData.getId();

       
        //返回成功,表示消息被正常投递
        if (ack) {
            //更新MSG表的消息发送状态。
           
        } else {
        	//注意失败会有好几个原因,需要更具失败原因分析,比如集群的情况下,3台机器只有1台收到,那么ack=false,
        	//但是如果是队列满了,也是返回false,那么我们后面在投递也是失败。
            logger.error("消费信息失败,messageId:{} 原因:{}",brokerMessageLog.getMessage_id(),cause);
        }
    }
};
/**
 * 信息投递的方法
 * @param order
 * @throws Exception
 */
public void send(Order order) throws Exception{
    //设置投递回调
    rabbitTemplate.setConfirmCallback(confirmCallback);
    CorrelationData correlationData = new CorrelationData();
    correlationData.setId(order.getMessage_id());

    //开始发送
    rabbitTemplate.convertAndSend("order-exchange","order.abcd", order, correlationData);
}

3、定时任务

/**
 * 系统启动后5秒开启定时任务 10秒执行一次
 */
@Scheduled(initialDelay = 5000, fixedDelay = 10000)
public void rabbitmqReSend() {

	//查询出下一次执行时间小于当前时间的日志记录并且状态为投递中,遍历结果集,判断重试次数是或大于3次,如果大于,将日志设置为投递失败,如果小于 则尝试重新投递,并改变数据库中日志的尝试次数
    list = brokerMessageLogMapper.selectByExample(brokerMessageLogExample);
            
    list.forEach(brokerMessageLog -> {
        if (brokerMessageLog.getTry_count() >= 3) {
            大于最大重试次数,更新发送状态为失败
        } else {
            更新发送次数,开发发送
            orderSender.send(JSONObject.parseObject(brokerMessageLog.getMessage(),Order.class));
        }

    });

}

四、MQ的创建

创建MQ的方式有很2种,一种是通过MQ管理后台,一种是通过代码创建MQ,下面是通过代码创建Queue、Exchange、Routekey

@Bean
public DirectExchange bookSceneExchange() {
    final DirectExchange exchange = new DirectExchange(config.getBookSceneExchange(), true, false);
    exchange.setAdminsThatShouldDeclare(defaultAmqpAdmin);
    return exchange;
}
@Bean
public Queue bookRouteQueue() {
    final Queue queue = new Queue(config.getBookRouteQueue(), true, false, false);
    queue.setAdminsThatShouldDeclare(defaultAmqpAdmin);
    return queue;
}
@Bean
public Binding bindingBookRouteQueue() {
    final Binding binding = BindingBuilder.bind(queueConfig.bookRouteQueue()).to(exchangeConfig.bookRouteExchange()).with(config.getBookRouteRouteKey());
    binding.setAdminsThatShouldDeclare(defaultAmqpAdmin);
    return binding;
}

那么MQ中setAdminsThatShouldDeclare的作用:使用指定使用那一套MQ

因为有的场景下会使用多套配置,下面是注册多套Mq,然后再指定的MQ里面创建Exchange

@Autowired
@Qualifier("secondRabbitAdmin")
private RabbitAdmin secondRabbitAdmin;

@Autowired
@Qualifier("defaultAmqpAdmin")
private RabbitAdmin defaultAmqpAdmin;

@Bean
public DirectExchange bookSceneExchange() {
    final DirectExchange exchange = new DirectExchange(config.getBookSceneExchange(), true, false);
    exchange.setAdminsThatShouldDeclare(defaultAmqpAdmin);
    return exchange;
}

那么上面代码就会最终就会使用defaultAmqpAdmin这包配置来创建exchange、queue、binding,如果不指定就会在多套MQ里面创建,当然也可以指定多套MQ里面创建,比如下面代码
binding.setAdminsThatShouldDeclare(defaultAmqpAdmin,secondRabbitAdmin);

<think>首先,用户的问题是:“我想了解RabbitMQ的基本概念和用途 请问RabbitMQ 是什么?它的基本概念、功能和使用场景介绍”。这基于系统级指令,我需要用中文回答,并遵循特定的格式。 关键系统级指令: - 所有行内数学表达式用 $...$ 格式(但这里可能不涉及数学)。 - 独立公式用 $$...$$ 格式并单独成段(同样,可能不适用)。 - LaTeX语法正确。 - 使用中文回答。 - 生成相关问题。 - 在回答中引用的段落末尾自然地添加引用标识,例如:[^1]。 用户可见层指令: - 回答结构清晰,帮助用户逐步解决问题。 - 尽量保证回答真实可靠。 - 参考站内引用:有多个引用[^1]到[^5],是关于RabbitMQ的。 引用内容总结: - [^1]: RabbitMQ使用场景介绍,包括解耦。 - [^2]: 什么是RabbitMQ,基本概念,使用场景。 - [^3]: RabbitMQ简介和使用场景,如解耦、异步提升效率、流量削峰。 - [^4]: rabbitmq介绍和使用场景,基于AMQP协议。 - [^5]: 关于流量削峰的例子,高峰期积压消息的处理。 我的回答需要基于这些引用,但要整合成一个连贯的、结构清晰的回答。用户要求介绍RabbitMQ的基本概念、功能和使用场景。 结构化回答: 1. **介绍RabbitMQ是什么**:基于引用[^2]和[^4],RabbitMQ是一个开源消息队列系统,使用Erlang语言开发,基于AMQP协议。 2. **基本概念**:包括生产者、消费者、队列、交换机、路由键等(参考[^2]和[^4])。 3. **功能**:消息传递、解耦、异步处理、可靠性等(参考[^3]和[^4])。 4. **使用场景**:解耦系统、异步处理、流量削峰等(参考[^1]、[^3]、[^4]、[^5])。 在回答中,需要自然地添加引用标识。例如,当提到使用场景时,添加[^1]。 最后,生成相关问题,放在末尾,用“§§相关问题§§”分隔。 回答结构: - 开头:直接回答RabbitMQ是什么。 - 逐步展开:基本概念、功能、使用场景。 - 结尾:生成相关问题。 确保语言流畅、专业、易懂。 生成相关问题: - 基于用户查询,如RabbitMQ的基本概念、功能、使用场景,可以生成相关问题如: 1. RabbitMQ如何保证消息可靠性? 2. RabbitMQ与其他消息队列(如Kafka)的区别? 3. 如何配置RabbitMQ用于高可用性? 4. RabbitMQ在微服务架构中的作用? 5. RabbitMQ的性能优化方法? 参考引用内容: - 从[^4]:AMQP协议的特征:面向消息、队列、路由、可靠性、安全。 - 从[^3]:使用场景:解耦、异步提升效率、流量削峰。 - 从[^5]:流量削峰的例子。 完整回答大纲: 1. RabbitMQ的定义和基本概念。 2. 核心功能。 3. 主要使用场景。 4. 相关问题。</think>### RabbitMQ的基本概念和用途介绍 RabbitMQ是一个开源的、基于AMQP(Advanced Message Queuing Protocol)协议的消息队列系统,使用Erlang语言开发。它主要用于分布式系统中消息的传递、存储和路由,帮助企业实现系统间的解耦、异步处理和流量控制。下面我将逐步介绍其基本概念、核心功能和使用场景,确保回答清晰可靠(基于可靠引用)。 #### 1. **RabbitMQ是什么?** RabbitMQ是一个消息代理(message broker),充当生产者和消费者之间的中间件。生产者发送消息到RabbitMQ,消费者从队列中接收并处理消息。这种设计实现了系统间的松耦合,避免了直接调用依赖。RabbitMQ基于AMQP协议,支持多种消息模式(如点对点、发布/订阅),并强调可靠性、安全性和可扩展性[^2][^4]。 #### 2. **基本概念** RabbitMQ的核心概念包括: - **生产者(Producer)**:发送消息的应用程序。 - **消费者(Consumer)**:接收和处理消息的应用程序。 - **队列(Queue)**:消息的存储区,确保消息按顺序被消费。队列RabbitMQ的核心组件,消息在队列中等待消费。 - **交换机(Exchange)**:接收生产者发送的消息,并根据路由规则(如路由键)将消息分发到队列。交换机类型包括直连(direct)、主题(topic)、扇出(fanout)等,支持灵活的消息路由[^2][^4]。 - **绑定(Binding)**:定义交换机和队列之间的连接规则,基于路由键(Routing Key)匹配消息。 - **消息(Message)**:传递的数据单元,包含头部信息(如路由键)和有效载荷(payload)。 - **虚拟主机(Virtual Host)**:逻辑隔离的环境,允许多个应用共享同一个RabbitMQ实例而不相互干扰[^2][^4]。 这些概念协同工作,形成一个可靠的消息传递系统。例如,生产者发送消息到交换机,交换机根据绑定规则路由到队列,消费者从队列拉取消息处理。 #### 3. **核心功能** RabbitMQ提供以下关键功能: - **消息传递**:支持异步通信,生产者发送消息后无需等待消费者响应,提高系统响应速度。 - **解耦**:分离生产者和消费者,允许系统组件独立开发和部署。例如,订单服务发送消息到RabbitMQ,库存服务异步消费,避免直接耦合[^1][^3]。 - **可靠性**:通过持久化(消息和队列可保存到磁盘)、确认机制(acknowledgments)和事务确保消息不丢失。AMQP协议内置了可靠性保证[^4]。 - **流量削峰**:在高并发时缓冲消息,防止系统过载。例如,电商大促时,请求峰值被MQ吸收,后台系统按稳定速率处理,避免崩溃[^3][^5]。 - **异步处理**:提升系统效率,例如用户注册后发送邮件通知,无需阻塞主线程[^3]。 - **路由灵活性**:通过交换机和绑定规则,支持多种消息模式(如广播、定向发送),适应复杂业务需求[^4]。 #### 4. **使用场景** RabbitMQ广泛应用于企业级系统,主要场景包括: - **系统解耦**:在微服务架构中,服务间通过消息队列通信,减少依赖。例如,订单系统与支付系统解耦,RabbitMQ作为中介传递消息,确保最终一致性[^1][^3]。 - **异步处理**:提升用户体验和系统吞吐量。例如,用户上传文件后,后台异步处理并通知结果,避免前台等待[^3]。 - **流量削峰**:应对突发流量。如电商秒杀活动,请求峰值积压在MQ中,后台系统稳定消费。高峰期积压的消息(如每分钟18万条)可在高峰期后快速处理(如1小时处理1000万条消息)[^5]。 - **日志收集和监控**:多个服务发送日志到RabbitMQ,中央系统统一消费和分析。 - **任务队列**:分布式任务调度,如定时任务或批处理作业分发[^3][^4]。 引入RabbitMQ的优点包括提高系统弹性、可扩展性和可靠性;但缺点是需要额外维护消息队列,可能引入复杂性(如消息顺序问题)[^3]。总体而言,RabbitMQ适合对数据一致性、稳定性和可靠性要求高的场景,如金融、电商和企业应用[^4]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

信仰_273993243

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值