• RabbitMQ常见问题


    1、如何确保消息正确地发送至RabbitMQ?

      两种解决方法:

    • 通过事务机制
      • 事务正常:
        • 客户端发送Tx.Select,将信道置为事务模式
        • Broker回复Tx.Select-Ok,确认已将信道设置为事务模式
        • 在发送完消息后,客户端发送Tx.Commit提交事务
        • Broker回复Tx.Commit-Ok确认事务提交 
      • 回滚:
        • 客户端发送Tx.Select,将信道置为事务模式
        • Broker回复Tx.Select-Ok,确认已将信道设置为事务模式
        • 事务提交之前出现异常,我们可以将其捕获,进而通过执行channel.exRollback方法实现事务回滚
    • 发送方确认
      • 信道设置为confirm模式,所有在该信道发送的消息都会被指派一个唯一ID
      • 一旦消息被投递到所匹配的队列中,给生产者发送一个Basic.ack消息(包含ID),这样使得生产者知道消息已到达目的地,如果消息和队列是持久化的,那么确认消息会在消息写入磁盘后发出。
      • 如果Rabbit因为自身内部错误导致消息丢失,就会发送一条Basic.Nack命令,生产者应用可以在回调函数中处理该Nack命令     
        public void syncSend(Integer id){
            ProducerSyncConfirmMessage message = new ProducerSyncConfirmMessage();
            message.setId(id);
            rabbitTemplate.invoke(new RabbitOperations.OperationsCallback<Object>() {
                
                @Override
                public Object doInRabbit(RabbitOperations operations) {
                    operations.convertAndSend(ProducerSyncConfirmMessage.EXCHANGE, ProducerSyncConfirmMessage.ROUTING_KEY, message);
                    logger.info("[doInRabbit][发送消息完成]");
                    operations.waitForConfirms(0); // timeout 参数,如果传递 0 ,表示无限等待
                    logger.info("[doInRabbit][等待 Confirm 完成]");
                    return null;
                }
            }, new ConfirmCallback() {
                @Override
                public void handle(long deliveryTag, boolean multiple) throws IOException {
                    logger.info("[handle][Confirm 成功]");
                }
            }, new ConfirmCallback() {
                @Override
                public void handle(long deliveryTag, boolean multiple) throws IOException {
                    logger.info("[handle][Confirm 失败]");
    
                }
            });
        }

    2、如何确保消息接收方消费了消息?

      ack机制,消费者在订阅队列时,可以指定autoAck参数:

    • autoAck == false :会等待消费者显示的回复信息后才从内存中删除(先标记,收到确认命令后删除),如果一直没有收到确认命令,并且此消费者已经断开连接,那么RabbitMQ会安排该消息重新进入队列。
    • autoAck == true : RabbitMQ会自动把发送出去的消息从内存中删除,不管消费者有没有消费

    3、如何避免消息重复消费?

      重复消费:保证消息唯一识别性,即使多次发送到消费者,消费者也可以检验是否已消费。

    4、消息如何分发?

    • 当RabbitMQ队列拥有多个消息者时,队列收到的信息将以轮询的分发方式发给消费者。每条消息都只会发送给订阅列表中的一个消费者。
    • 默认情况下,如果有n个消费者,那么RabbitMQ会将第m条消息分发给第m%n(取余)个消费者,RabbitMQ不管消费者是否消费并经确认(Basic.Ack)了消息

      如果某些消费者业务繁重,来不及消费这么多消息,而某些消费者由于某些原因很快结束了,进而进程空闲那么造成整体吞吐量下降。可以使用channel.basicQos(int prefetchCount)方法,该方法允许限制信道上的消费者所能保持的最大未确认消息的数量。举例说明:如果订阅消费列表之前,消费端调用了channel.basicQos(5),之后订阅了某个队列进行消费。RabbitMQ会先保存一个消费者的队列,每发送一条消息都会为对应的消费者计数,如果达到所设定的上线。RabbitMQ不会向这个消费者发送消息,待消费者确认消费某条消息之后,计数-1,之后消费者就可以继续接收消息了。

    5、消息怎么路由?

      生产者发送消息到交换器,交换器根据绑定(RoutingKey 和 BindingKey根据交换器的类型)匹配对应的Queue 

      Exchange由四个类型:fanout、direct、topic、headers

    6、如何确保消息不丢失?

    • 生产者发送消息丢失:可以采取生产者confirm模式 ,autoAck == false,如果没有收到Basic.Ack命令需要进行消息补偿:
      • 第一种:消息发送前落库并进行状态标记,待收到确认信号再更改状态。定时任务检查超时没有收到确认的消息,进行重发但是要设置重发次数。达到一定次数进行异常处理人工介入
      • 第二种:
        • 生产者生产两条消息,一条立即发送给下游服务,一条延迟消息给补偿(callback Server)服务
        • 下游服务监听到这个消息后,会发送一条消息到callback Server
        • callback Server监听到这个消息后,知道刚才有条消息消费成功了,然后把这个持久化到数据库中,当上游服务发送的延迟消息到达callback Server时,就会查询db是否存在对应的消息。如果存在就代表已经被消费了。如果不存在这条记录,那么callback Server就会发送一个RPC请求到上游进行消息重发。
    • rabbitmq消息丢失:将队列和消息都持久化(队列:durable == true 、消息:deliveryMode == 2),但是RabbitMQ不会为每条消息进行磁盘同步,可能先写入缓存(三个策略:),待缓存满了之后再进行写磁盘操作。那么这段时间服务器宕机也会带来消息的问题,解决的方案就是镜像队列,如果master节点宕机,可以自动切换到从节点,这样有效保证了高可用性。
    • 消费者丢失消息:消费者confirm模式,autoAck == false

    7、保证消息队列的高可用?

      开启镜像集群模式,你创建的queue,无论元数据还是queue里的消息都会存在于多个实例上,然后每次你写消息到queue的时候,都会自动把消息到多个实例的queue里进行消息同步。

    8、保证消息的顺序性?

    • 拆分多个queue,每个queue一个consumer,这样也会造成吞吐量下降,可以在消费者内部采用多线程的方式取消费。

    • 或者就一个queue但是对应一个consumer,然后这个consumer内部用内存队列做排队,然后分发给底层不同的worker来处理

  • 相关阅读:
    UIProgressView的详细使用
    Android拍照上传代码样例
    UILabel的详细使用及特殊效果
    TextView属性android:ellipsize实现跑马灯效果
    Android中WebView实现Javascript调用Java类方法
    有效获取状态栏(StatusBar)高度
    详解iPhone Tableview分批显示数据
    TextView显示插入的图片
    ObjectiveC语法快速参考
    UISegmentedControl的详细使用
  • 原文地址:https://www.cnblogs.com/TripL/p/13378510.html
Copyright © 2020-2023  润新知