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

来源:互联网 发布:中国土壤数据库 编辑:程序博客网 时间:2024/06/05 19:48

上两篇博文简单介绍了下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的这三个配置就简单的介绍到这儿了~

0 0
原创粉丝点击