RabbitMQ——常见的函数介绍

在前面一篇文章的案例中,如果开启两个Receive,消息被平均发送给了2个Receive。
很多情况下,我们并不希望消息平均分配,可以对代码做如下修改。

场景:a侦听器处理快,b侦听器处理的慢,我们希望能将更多的消息分配给a。 

import cn.swsk.springboot.rgyx.jx.test.ConnectionUtil;
import com.rabbitmq.client.*;

import java.io.IOException;
import java.nio.charset.StandardCharsets;

/**
 * @author Mr.css
 * @date 2020-11-12 9:31
 */
public class Receive {
    private static final String QUEUE_NAME = "queue_name";

    public static void main(String[] args) {
        try {
            Connection connection = ConnectionUtil.getConnection();
            Channel channel = connection.createChannel();
            channel.queueDeclare(QUEUE_NAME, false, false, false, null);

            //限制消息接收的数量
            channel.basicQos(0,1,false);

            DefaultConsumer consumer = new DefaultConsumer(channel) {

                @Override
                public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties,
                                           byte[] body) {
                    String message = new String(body, StandardCharsets.UTF_8);
                    System.out.println("[Receive]:" + message);

                    try {
                        Thread.sleep(500);
                        //手动应答
                        channel.basicAck(envelope.getDeliveryTag(), false);
                    } catch (InterruptedException | IOException e) {
                        e.printStackTrace();
                    }
                }
            };
            //自动应答设置为false
            channel.basicConsume(QUEUE_NAME, false, consumer);
        } catch (IOException | ShutdownSignalException | ConsumerCancelledException e) {
            e.printStackTrace();
        }
    }
}

案例中用到的函数/参数介绍

basicQos()

These settings impose limits on the amount of data the server will deliver to consumers before requiring acknowledgements.Thus they provide a means of consumer-initiated flow control.
这些设置限制了服务器在请求确认之前将发送给消费者的数据量。因此,它们提供了一种消费者发起的流量控制方法。

Qos(Quality of Service)直译是:服务质量,但是感觉,理解为带宽分配、流量控制会更加合理

参数:

prefetchSize:服务器将提供的最大内容量(以字节为单位),如果没有限制则为0,似乎必须为0,程序执行到此报错,说还没有实现不为0的情况。
maximum amount of content (measured in octets) that the server will deliver, 0 if unlimited

prefetchCount:服务器将发送的最大消息数,如果没有限制,则为0。
maximum number of messages that the server will deliver, 0 if unlimited

global:设置是否应用于整个Connection,一个Connection可以有多个Channel,false则只对当前Channel有效。
true if the settings should be applied to the entire channel rather than each consumer

basicConsume()

第二个参数的作用:
如果是true消息一经发送,服务器就认为消息已经收到;如果是false,表示服务器期望取得明确的结果。
true if the server should consider messages acknowledged once delivered; false if the server should expect explicit acknowledgements。


basicAck()

ACK(Acknowledge character) 确认消息、确认字符,详细可收索词条 “ACK应答”。

这个函数可以应答一个或多个消息(声明已经处理好了这些消息),第二个参数,true表示截止至目前的所有tag(包括当前tag);false表示只包含当前的tag。

true to acknowledge all messages up to and including the supplied delivery tag; false to acknowledge just the supplied delivery tag.

Envelope

这个对象的直译是信封,这个名称非常形象,记录了消息的来源、去向、唯一编码、是否重新投递过。


private final long _deliveryTag;
private final boolean _redeliver;
private final String _exchange;
private final String _routingKey;

_deliveryTag每个channel对应一个tag,每次消息投递或者重新投递,tag都会增加

消息的拒绝策略

与basicAck()功能相反的函数,不想处理的消息,可以拒绝退回,消息拒绝的两个函数的参数是一样的,basicNack可以一次性拒绝多个
channel.basicNack();
channel.basicReject();

其它需要考虑的问题:
在消息处理过程中,如果发生异常,需要考虑服务降级的策略(异常处理代码)。
有个很常见的做法,就是将消息重新放进队列,如果第二次处理的时候,触发完全相同的异常,就产生无线循环了。
在队列的相关设计中,很容易遇到这种问题,需要根据自己的业务需求进行定制。
(这种问题也会发生在:线程池)

 

posted on 2022-03-25 17:19  疯狂的妞妞  阅读(64)  评论(0编辑  收藏  举报

导航