【RabbitMQ之简单队列】

本文介绍了RabbitMQ中的简单队列模型,强调了Queue作为存储消息的核心角色。生产者将消息发送到Queue,而消费者可以从Queue接收并处理消息。在多消费者订阅同一Queue的情况下,消息会被平均分配。此外,文章还概述了生产者和消费者的编码实践,包括创建连接、channel、queue以及消息的生产和消费步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

简单队列模型

Queue

Queue(队列)是RabbitMQ的内部对象,用于存储消息,用下图表示。

RabbitMQ中的消息都只能存储在Queue中,生产者(下图中的P)生产消息并最终投递到Queue中,消费者(下图中的C)可以从Queue中获取消息并消费。

 

多个消费者可以订阅同一个Queue,这时Queue中的消息会被平均分摊给多个消费者进行处理,而不是每个消费者都收到所有的消息并处理。

编码实践

一、生产者和消费者模型

1、创建连接(生产端)

 Connection connection = null;
 ConnectionFactory connectionFactory = new ConnectionFactory();
 connectionFactory.setHost("youHost");
 connectionFactory.setUsername("userName");
 connectionFactory.setPassword("password");
 connection = connectionFactory.newConnection();

 

2、创建channel(生产端)

Channel channel = connection.createChannel();

3、创建queue(生产端)

channel.queueDeclare("队列名称",false,false,false,null);
 
源码:
queueDeclare(String queue, boolean durable, boolean exclusive, boolean autoDelete,
                                 Map<String, Object> arguments)
/**
 * Construct a new queue, given a name, durability flag, and auto-delete flag, and arguments.
 * @param name the name of the queue - must not be null; set to "" to have the broker generate the name.
 * @param durable true if we are declaring a durable queue (the queue will survive a server restart)
 * @param exclusive true if we are declaring an exclusive queue (the queue will only be used by the declarer's
 * connection)
 * @param autoDelete true if the server should delete the queue when it is no longer in use
 * @param arguments the arguments used to declare the queue
 */
public Queue(String name, boolean durable, boolean exclusive, boolean autoDelete, Map<String, Object> arguments) {
   Assert.notNull(name, "'name' cannot be null");
   this.name = name;
   this.actualName = StringUtils.hasText(name) ? name
         : (Base64UrlNamingStrategy.DEFAULT.generateName() + "_awaiting_declaration");
   this.durable = durable;
   this.exclusive = exclusive;
   this.autoDelete = autoDelete;
   this.arguments = arguments != null ? arguments : new HashMap<>();
}

参数介绍:
1、name: 队列的名称;
2、actualName: 队列的真实名称,默认用name参数,如果name为空,则根据规则生成一个;
3、durable: 是否持久化;
4、exclusive: 是否独享、排外的;
5、autoDelete: 是否自动删除;
6、arguments:队列的其他属性参数,有如下可选项
(1)x-message-ttl:消息的过期时间,单位:毫秒;
(2)x-expires:队列过期时间,队列在多长时间未被访问将被删除,单位:毫秒;
(3)x-max-length:队列最大长度,超过该最大值,则将从队列头部开始删除消息;
(4)x-max-length-bytes:队列消息内容占用最大空间,受限于内存大小,超过该阈值则从队列头部开始删除消息;
(5)x-overflow:设置队列溢出行为。这决定了当达到队列的最大长度时消息会发生什么。有效值是drop-head、reject-publish或reject-publish-dlx。仲裁队列类型仅支持drop-head;
(6)x-dead-letter-exchange:死信交换器名称,过期或被删除(因队列长度超长或因空间超出阈值)的消息可指定发送到该交换器中;
(7)x-dead-letter-routing-key:死信消息路由键,在消息发送到死信交换器时会使用该路由键,如果不设置,则使用消息的原来的路由键值
(8)x-single-active-consumer:表示队列是否是单一活动消费者,true时,注册的消费组内只有一个消费者消费消息,其他被忽略,false时消息循环分发给所有消费者(默认false)
(9)x-max-priority:队列要支持的最大优先级数;如果未设置,队列将不支持消息优先级;
(10)x-queue-mode(Lazy mode):将队列设置为延迟模式,在磁盘上保留尽可能多的消息,以减少RAM的使用;如果未设置,队列将保留内存缓存以尽可能快地传递消息;
(11)x-queue-master-locator:在集群模式下设置镜像队列的主节点信息。

4、生产消息

 

在不创建exchange的场景下,routeKey使用队列名称,rabbitmq会使用默认的AMQP default 交换机,具体的规则如上述解释。

channel.basicPublish("","队列名称",null,(msg + i).getBytes());
源码:

    /**
     * Publish a message
     * @see com.rabbitmq.client.AMQP.Basic.Publish
     * @param exchange the exchange to publish the message to
     * @param routingKey the routing key
     * @param mandatory true if the 'mandatory' flag is to be set
     * @param immediate true if the 'immediate' flag is to be
     * set. Note that the RabbitMQ server does not support this flag.
     * @param props other properties for the message - routing headers etc
     * @param body the message body
     * @throws java.io.IOException if an error is encountered
     */
public void basicPublish(String exchange, String routingKey,
                             boolean mandatory, boolean immediate,
                             BasicProperties props, byte[] body)
        throws IOException
    {
        if (nextPublishSeqNo > 0) {
            unconfirmedSet.add(getNextPublishSeqNo());
            nextPublishSeqNo++;
        }
        BasicProperties useProps = props;
        if (props == null) {
            useProps = MessageProperties.MINIMAL_BASIC;
        }
        transmit(new AMQCommand(new Basic.Publish.Builder()
                                    .exchange(exchange)
                                    .routingKey(routingKey)
                                    .mandatory(mandatory)
                                    .immediate(immediate)
                                .build(),
                                useProps, body));
    }
exchange 交换机名称
routingKey 路由键
mandatory true时,交换器无法根据自动的类型和路由键找到一个符合条件的队列,那么RabbitMq会调用Basic.Ruturn命令将消息返回给生产者,为false时,出现上述情况消息被直接丢弃
immediate true,如果交换器在消息路由到队列时发现没有任何消费者,那么这个消息将不会存和队列,当与路由匹配的所有队列都没有消费者时,会Basic.Return返回给生产者3.0去掉了immediate 参数
immediate和mandatory 都是消息传递过程中,不可达目的地是,将消息返回给生产者的功能
props:
    contentType:消息的内容类型,如:text/plain
    contentEncoding:消息内容编码
    headers:设置消息的header,类型为Map<String,Object>
    deliveryMode:1(nopersistent)非持久化,2(persistent)持久化
    priority:消息的优先级
    correlationId:关联ID
    replyTo:用于指定回复的队列的名称
    expiration:消息的失效时间
    messageId:消息ID
    timestamp:消息的时间戳
    type:类型
    userId:用户ID
    appId:应用程序ID
    custerId:集群ID

1、创建连接(消费者端)

 Connection connection = null;
 ConnectionFactory connectionFactory = new ConnectionFactory();
 connectionFactory.setHost("you host");
 connectionFactory.setUsername("xxxx");
 connectionFactory.setPassword("xxxx");
 connection = connectionFactory.newConnection();

2、创建channel(消费者端)

Channel channel = connection.createChannel();

3、创建消费者(消费者端)

QueueingConsumer consumer = new QueueingConsumer(channel);

4、监听消息队列(消费者端)

 channel.basicConsume("队列名称", consumer);
源码:
/**
     * Start a consumer. Calls the consumer's {@link Consumer#handleConsumeOk}
     * method.
     * @param queue the name of the queue
     * @param autoAck true if the server should consider messages
     * acknowledged once delivered; false if the server should expect
     * explicit acknowledgements
     * @param consumerTag a client-generated consumer tag to establish context
     * @param noLocal true if the server should not deliver to this consumer
     * messages published on this channel's connection
     * @param exclusive true if this is an exclusive consumer
     * @param callback an interface to the consumer object
     * @param arguments a set of arguments for the consume
     * @return the consumerTag associated with the new consumer
     * @throws java.io.IOException if an error is encountered
     * @see com.rabbitmq.client.AMQP.Basic.Consume
     * @see com.rabbitmq.client.AMQP.Basic.ConsumeOk
     */
public String basicConsume(String queue, boolean autoAck, String consumerTag, boolean noLocal, boolean exclusive, Map<String, Object> arguments, Consumer callback) throws IOException {
        final String result = delegate.basicConsume(queue, autoAck, consumerTag, noLocal, exclusive, arguments, callback);
        recordConsumer(result, queue, autoAck, exclusive, arguments, callback);
        return result;
    }

String queue 队列名
boolean autoAck 是否自动确认消息,true自动确认,false 不自动要手动调用,建立设置为false
String consumerTag 消费者标签,用来区分多个消费者
boolean noLocal 设置为true,表示 不能将同一个Conenction中生产者发送的消息传递给这个Connection中 的消费者
boolean exclusive 排他消费者,即这个队列只能由一个消费者消费.适用于任务不允许进行并发处理的情况下.
Map<String, Object> arguments 消费者的参数
Consumer callback 消费者 DefaultConsumer建立使用,重写其中的方法

5、消费消息(消费者端)

QueueingConsumer.Delivery delivery = null;
 try{
       while (( delivery = consumer.nextDelivery()) != null){
       byte[] body = delivery.getBody();
       String msg = new String(body);
       System.out.println(msg);
       }
     }
 catch (InterruptedException e){
    e.printStackTrace();
 }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值