二.多个消费者同时消费一个列队

来源:互联网 发布:java文件比较 编辑:程序博客网 时间:2024/05/01 01:15

提供者的pom.xml和消费者的pom.xml和第一章一样
一.Producer提供者
发送消息的类:MessageSender.java

package com.rabbitmq.producer;import java.io.IOException;import java.util.concurrent.TimeoutException;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import com.rabbitmq.client.Channel;import com.rabbitmq.client.Connection;import com.rabbitmq.client.ConnectionFactory;public class MessageSender {    private Logger logger = LoggerFactory.getLogger(MessageSender.class);    //声明一个列队名字    private final static String QUEUE_NAME = "hello";    /**     * 多个消费者同时消费一个列队测试     * 发送者不停的往MQ中发送消息     * @param message     * @return     */    public boolean sendMessageMany(String message){        //new一个rabbitmq的连接工厂        ConnectionFactory factory = new ConnectionFactory();        //设置需要连接的RabbitMQ的机器的地址,这里指向本机        factory.setHost("localhost");        //连接器        Connection connection = null;        //通道        Channel channel = null;        try {            //尝试获取一个连接            connection = factory.newConnection();            //尝试创建一个通道            channel = connection.createChannel();            /*声明一个列队:             * 1.queue队列的名字,是否持久化 为true则在rabbitMQ重启后生存,             * 2.是否是排他性队列(别人看不到),只对当前连接有效,当前连接断开后,队列删除(设置了持久化也删除)             * 3.自动删除,在最后一个连接断开后删除队列             * 4.其他参数             * */            channel.queueDeclare(QUEUE_NAME,false,false,false,null);            /*发布消息,注意这里调用了getBytes(),发送的其实是byte数组,接收方收到消息后,需要重新组装成String             * 1.交换模式             * 2.控制消息发送到哪个队列             * 3.其他参数             * 4.body 消息,byte数组             * */            //循环往列队发布消息            int i = 0;            String oldMessage = message;            while(true){                message+=i++;                channel.basicPublish("", QUEUE_NAME, null, message.getBytes());                logger.info("已发送:"+message);                try {                    Thread.sleep(500);//500毫秒发送一次                } catch (InterruptedException e) {                    logger.info("线程被打断:"+message);                }                message=oldMessage;//还原消息                //此代码没用,只是为了死循环出现防止编译出错                if(!"q".equals("q")){                    break;                }            }            //关闭通道和链接(先关闭通道在关闭连接)            channel.close();            connection.close();        } catch (IOException e) {            logger.error("IO异常:"+e);            return false;        } catch (TimeoutException e){            logger.error("超时异常:"+e);            return false;        }        return true;    }}

2.测试发送消息的Main:ManySenderMain.java

package com.rabbitmq.main;import com.rabbitmq.producer.MessageSender;public class ManySenderMain {    public static void main(String[] args) {        MessageSender messageSender = new MessageSender();        messageSender.sendMessageMany("hellow tiglle");    }}

二.Consumer消费者:

1.接收消息的消费者类:

package com.rabbitmq.consumer;import java.io.IOException;import java.util.concurrent.TimeoutException;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import com.rabbitmq.client.AMQP;import com.rabbitmq.client.Channel;import com.rabbitmq.client.Connection;import com.rabbitmq.client.ConnectionFactory;import com.rabbitmq.client.Consumer;import com.rabbitmq.client.DefaultConsumer;import com.rabbitmq.client.Envelope;public class MessageRecive {    private Logger logger = LoggerFactory.getLogger(MessageRecive.class);    //多个消费者消费消息:增加了是哪个消费者的标记    public boolean manyConsume(String queueName,final String flag){        //连接rabbitmq        ConnectionFactory factory = new ConnectionFactory();        factory.setHost("localhost");        Connection connection = null;        Channel channel =null;        //声明消费的queue        try {            connection = factory.newConnection();            channel = connection.createChannel();            channel.queueDeclare(queueName,false,false,false,null);            //这里重写了DefaultConsumer的handleDelivery方法,因为发送的时候对消息进行了getByte(),在这里要重新组装成String            Consumer consumer = new DefaultConsumer(channel){                //重写父类方法                @Override                public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body)throws IOException {                    String message = new String(body, "UTF-8");                    logger.info("["+flag+"]接收到:" + message);                }            };            //上面是声明消费者,这里用 声明的消费者  消费  列队的消息            channel.basicConsume(queueName, true,consumer);            //这里不能关闭连接,调用了消费方法后,消费者会一直连接着rabbitMQ等待消费        } catch (Exception e) {            logger.error("出现异常:"+e);            return false;        }        return true;    }}

3.测试启动多个消费者开始监听消费消息的Main方法:ManyReviceMain.java

package com.rabbitmq.main;import com.rabbitmq.consumer.MessageRecive;//多个消费之同时消费列队的消息public class ManyReviceMain {    //这个队列名字要和生产者中的名字一样,否则找不到队列    private final static String QUEUE_NAME = "hello";    /**     * 测试多个客户端消费提供者的消息     * 可以看出消息会平均发送个每个消费者     * RabbitMQ的特性,称作“Round-robin dispatching”,消息会平均的发送给每一个消费者     * @param args     */    public static void main(String[] args) {        MessageRecive messageRecive1 = new MessageRecive();        messageRecive1.manyConsume(QUEUE_NAME, "consumer1");        MessageRecive messageRecive2 = new MessageRecive();        messageRecive2.manyConsume(QUEUE_NAME, "consumer2");        MessageRecive messageRecive3 = new MessageRecive();        messageRecive3.manyConsume(QUEUE_NAME, "consumer3");        MessageRecive messageRecive4 = new MessageRecive();        messageRecive4.manyConsume(QUEUE_NAME, "consumer4");    }}

可以看到,提供者不停的发送消息,四个消费者是平均规律的分摊了消费者的消息。
RabbitMQ的特性,称作“Round-robin dispatching”,消息会平均的发送给每一个消费者

阅读全文
0 0