rabbitmq学习之路(三)消息应答、持久化以及公平转发

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qiyongkang520/article/details/60781232

上两篇博文简单介绍了下rabbitmq的使用方式,接下来,笔者再给大家介绍下rabbitmq的基础配置:设置消息的应答、持久化以及公平转发。
下面,笔者简单的来解释下这个三个配置:
1. 消息应答:
默认情况下,只要有消费者,消息进去队列后,消息就会被全部分配好到相应的消费者进行处理,对应的消息也会在队列中去除。如果某个消费者处理过程中突然挂了,那么这些消息就没有被处理,所以我们可以设置消息为应答模式,也就是在消费者处理完一条消息后,就告诉mq此消息已被处理完,那么未作出应答的消息就会被转发到其它的消费者进行处理。
2. 消息持久化:
如果我们不设置消息持久化,那么在服务器重启后,所有的队列以及相应的数据都会丢失,所以设置持久化,相应的数据就会保存在磁盘中,不会丢失。
3. 公平转发
由于队列中的消息的分配机制,会导致某些消费者一直处于繁忙的状态,而让其他处理完的消费者处于等待状态,就算再新增一个消费者也不会把消息分配到此消费者,所以我们可以设置公平转发,这样可以保证多个消费者之间公平的处理消息,同时还可以动态新增消费者加入工作。

好了,接下来,给大家看看相应的代码,说明已于注释中:
生产者:

/**
 * Project Name:qyk_testJava
 * File Name:Producer.java
 * Package Name:com.qiyongkang.mq.rabbitMq.basic
 * Date:2017年3月6日下午5:27:59
 * Copyright (c) 2017, Thinkive(http://www.thinkive.com/) All Rights Reserved.
 *
*/

package com.qiyongkang.mq.rabbitMq.basic;

import java.io.IOException;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.MessageProperties;

/**
 * ClassName:Producer <br/>
 * Function: TODO ADD FUNCTION. <br/>
 * Reason: TODO ADD REASON. <br/>
 * Date: 2017年3月6日 下午5:27:59 <br/>
 * 
 * @author qiyongkang
 * @version
 * @since JDK 1.6
 * @see
 */
public class Producer {
    // 队列名称
    private final static String QUEUE_NAME = "qyk.basic";

    public static void main(String[] args) throws IOException {
        // 创建连接和频道
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        Connection connection = factory.newConnection();
        Channel channel = connection.createChannel();
        //  声明队列, 设置队列持久化
        boolean durable = true;
        channel.queueDeclare(QUEUE_NAME, durable, false, false, null);
        // 发送10条消息,依次在消息后面附加1-10个点
        for (int i = 0; i < 10; i++) {
            String dots = "";
            for (int j = 0; j <= i; j++) {
                dots += ".";
            }
            String message = "helloworld" + dots + dots.length();
            channel.basicPublish("", QUEUE_NAME, MessageProperties.PERSISTENT_TEXT_PLAIN, message.getBytes());
            System.out.println(" [x] Sent '" + message + "'");
        }
        // 关闭频道和资源
        channel.close();
        connection.close();

    }
}

消费者:

/**
 * Project Name:qyk_testJava
 * File Name:Consumer.java
 * Package Name:com.qiyongkang.mq.rabbitMq.basic
 * Date:2017年3月6日下午5:27:51
 * Copyright (c) 2017, Thinkive(http://www.thinkive.com/) All Rights Reserved.
 *
*/

package com.qiyongkang.mq.rabbitMq.basic;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.QueueingConsumer;

/**
 * ClassName:Consumer <br/>
 * Function: TODO ADD FUNCTION. <br/>
 * Reason: TODO ADD REASON. <br/>
 * Date: 2017年3月6日 下午5:27:51 <br/>
 * 
 * @author qiyongkang
 * @version
 * @since JDK 1.6
 * @see
 */
public class Consumer {
    // 队列名称
    private final static String QUEUE_NAME = "qyk.basic";

    public static void main(String[] argv) throws java.io.IOException, java.lang.InterruptedException {
        // 区分不同工作进程的输出
        int hashCode = Thread.currentThread().hashCode();
        // 创建连接和频道
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        Connection connection = factory.newConnection();
        Channel channel = connection.createChannel();
        // 声明队列、设置队列持久化
        boolean durable = true;
        channel.queueDeclare(QUEUE_NAME, durable, false, false, null);
        System.out.println(hashCode + " [*] Waiting for messages. To exit press CTRL+C");

        //设置最大服务转发消息数量, 公平转发
        int prefetchCount = 1;
        channel.basicQos(prefetchCount);

        QueueingConsumer consumer = new QueueingConsumer(channel);
        // 指定消费队列,打开应答机制, 注意false才是打开手动应对
        boolean ack = false ; 
        channel.basicConsume(QUEUE_NAME, ack, consumer);
        while (true) {
            QueueingConsumer.Delivery delivery = consumer.nextDelivery();
            String message = new String(delivery.getBody());

            System.out.println(hashCode + " [x] Received '" + message + "'");
            doWork(message);
            System.out.println(hashCode + " [x] Done");

            //另外需要在每次处理完成一个消息后,手动发送一次应答。
            channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
        }

    }

    /**
     * 每个点耗时1s
     * 
     * @param task
     * @throws InterruptedException
     */
    private static void doWork(String task) throws InterruptedException {
        for (char ch : task.toCharArray()) {
            if (ch == '.')
                Thread.sleep(1000);
        }
    }
}

这里,我们把消费者运行多次,就可以模拟多个消费者了。
好了,rabbitmq的这三个配置就简单的介绍到这儿了~

猜你喜欢

转载自blog.csdn.net/qiyongkang520/article/details/60781232