从本节开始称Sender为生产者 , Recv为消费者

 

一、消息确认

为了确保消息一定被消费者处理,rabbitMQ提供了消息确认功能,就是在消费者处理完任务之后,就给服务器一个回馈,服务器就会将该消息删除,如果消费者超时不回馈,那么服务器将就将该消息重新发送给其他消费者

默认是开启的,在消费者端通过下面的方式开启消息确认,  首先将autoAck自动确认关闭,等我们的任务执行完成之后,手动的去确认,类似JDBC的autocommit一样

  1.  
  1. QueueingConsumer consumer = new QueueingConsumer(channel);
  2. boolean autoAck = false;
  3. channel.basicConsume("hello", autoAck, consumer);
  1.  

在前面的例子中使用的是channel.basicConsume(channelName, true, consumer) ; 在接收到消息后,就会自动反馈一个消息给服务器。

下面这个例子来测试消息确认的功能。

Sender03.java

  1. package com.zf.rabbitmq03;
  2.  
  3. import java.io.IOException;
  4.  
  5. import com.rabbitmq.client.Channel;
  6. import com.rabbitmq.client.Connection;
  7. import com.rabbitmq.client.ConnectionFactory;
  8.  
  9. /**
  10. * 发送消息
  11. * @author zhoufeng
  12. *
  13. */
  14. public class Sender03 {
  15.  
  16. public static void main(String[] args) throws IOException {
  17.  
  18. ConnectionFactory connFac = new ConnectionFactory() ;
  19.  
  20. //RabbitMQ-Server安装在本机,所以直接用127.0.0.1
  21. connFac.setHost("127.0.0.1");
  22.  
  23. //创建一个连接
  24. Connection conn = connFac.newConnection() ;
  25.  
  26. //创建一个渠道
  27. Channel channel = conn.createChannel() ;
  28.  
  29. //定义Queue名称
  30. String queueName = "queue01" ;
  31.  
  32. //为channel定义queue的属性,queueName为Queue名称
  33. channel.queueDeclare( queueName , false, false, false, null) ;
  34.  
  35. String msg = "Hello World!";
  36.  
  37. //发送消息
  38. channel.basicPublish("", queueName , null , msg.getBytes());
  39.  
  40. System.out.println("send message[" + msg + "] to "+ queueName +" success!");
  41.  
  42. channel.close();
  43. conn.close();
  44.  
  45. }
  46.  
  47. }

与Sender01.java一样,没有什么区别。

Recv03.java

  1. package com.zf.rabbitmq03;
  2.  
  3. import java.io.IOException;
  4.  
  5. import com.rabbitmq.client.Channel;
  6. import com.rabbitmq.client.Connection;
  7. import com.rabbitmq.client.ConnectionFactory;
  8. import com.rabbitmq.client.ConsumerCancelledException;
  9. import com.rabbitmq.client.QueueingConsumer;
  10. import com.rabbitmq.client.QueueingConsumer.Delivery;
  11. import com.rabbitmq.client.ShutdownSignalException;
  12.  
  13. /**
  14. * 接收消息
  15. * @author zhoufeng
  16. *
  17. */
  18. public class Recv03 {
  19.  
  20. public static void main(String[] args) throws IOException, ShutdownSignalException, ConsumerCancelledException, InterruptedException {
  21.  
  22. ConnectionFactory connFac = new ConnectionFactory() ;
  23.  
  24. connFac.setHost("127.0.0.1");
  25.  
  26. Connection conn = connFac.newConnection() ;
  27.  
  28. Channel channel = conn.createChannel() ;
  29.  
  30. String channelName = "channel01";
  31.  
  32. channel.queueDeclare(channelName, false, false, false, null) ;
  33.  
  34. //配置好获取消息的方式
  35. QueueingConsumer consumer = new QueueingConsumer(channel) ;
  36.  
  37. //取消 autoAck
  38. boolean autoAck = false ;
  39.  
  40. channel.basicConsume(channelName, autoAck, consumer) ;
  41.  
  42. //循环获取消息
  43. while(true){
  44.  
  45. //获取消息,如果没有消息,这一步将会一直阻塞
  46. Delivery delivery = consumer.nextDelivery() ;
  47.  
  48. String msg = new String(delivery.getBody()) ;
  49.  
  50. //确认消息,已经收到
  51. channel.basicAck(delivery.getEnvelope().getDeliveryTag()
  52. , false);
  53.  
  54. System.out.println("received message[" + msg + "] from " + channelName);
  55. }
  56.  
  57. }
  58.  
  59. }

注意:一旦将autoAck关闭之后,一定要记得处理完消息之后,向服务器确认消息。否则服务器将会一直转发该消息

如果将上面的channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);注释掉, Sender03.java只需要运行一次 , Recv03.java每次运行将都会收到HelloWorld消息

注意:

但是这样还是不够的,如果rabbitMQ-Server突然挂掉了,那么还没有被读取的消息还是会丢失 ,所以我们可以让消息持久化。 只需要在定义Queue时,设置持久化消息就可以了,方法如下:

  1.  
  1. boolean durable = true;
  2. channel.queueDeclare(channelName, durable, false, false, null);
  1.  

这样设置之后,服务器收到消息后就会立刻将消息写入到硬盘,就可以防止突然服务器挂掉,而引起的数据丢失了。  但是服务器如果刚收到消息,还没来得及写入到硬盘,就挂掉了,这样还是无法避免消息的丢失。

 

二、公平调度

上一个例子能够实现发送一个Message与接收一个Message

从上一个Recv01中可以看出,必须处理完一个消息,才会去接收下一个消息。如果生产者众多,那么一个消费者肯定是忙不过来的。此时就可以用多个消费者来对同一个Channel的消息进行处理,并且要公平的分配任务给多个消费者。不能部分很忙  部分总是空闲

实现公平调度的方式就是让每个消费者在同一时刻会分配一个任务。 通过channel.basicQos(1);可以设置

rabbitMQ学习笔记(三) 消息确认与公平调度消费者的更多相关文章

  1. RabbitMQ 消息确认与公平调度消费者

    一.消息确认 为了确保消息一定被消费者处理,rabbitMQ提供了消息确认功能,就是在消费者处理完任务之后,就给服务器一个回馈,服务器就会将该消息删除,如果消费者超时不回馈,那么服务器将就将该消息重新 ...

  2. rabbitMQ学习笔记(五) 消息路由

    生产者会生产出很多消息 , 但是不同的消费者可能会有不同的需求,只需要接收指定的消息,其他的消息需要被过滤掉. 这时候就可以对消息进行过滤了. 在消费者端设置好需要接收的消息类型. 如果不使用默认的E ...

  3. Linux内核学习笔记(7)--完全公平调度(CFS)

    一.完全公平调度算法 完全公平调度 CFS 的出发点基于一个简单的理念:进程调度的效果应该如同系统具备一个理想中的完美多任务处理器.在这种系统中,每个进程能够获得 1/n 的处理器时间(n 为可运行进 ...

  4. RabbitMQ学习笔记三:Java实现RabbitMQ之与Spring集成

    搭建好maven项目环境,加入RabbitMQ依赖包 <dependency> <groupId>org.springframework.amqp</groupId> ...

  5. RabbitMQ学习笔记五:RabbitMQ之优先级消息队列

    RabbitMQ优先级队列注意点: 1.只有当消费者不足,不能及时进行消费的情况下,优先级队列才会生效 2.RabbitMQ3.5以后才支持优先级队列 代码在博客:RabbitMQ学习笔记三:Java ...

  6. RabbitMQ学习系列三-C#代码接收处理消息

    RabbitMQ学习系列三:.net 环境下 C#代码订阅 RabbitMQ 消息并处理 http://www.80iter.com/blog/1438251320680361 http://www. ...

  7. rabbitmq学习(三) —— 工作队列

    工作队列,又称任务队列,主要思想是避免立即执行资源密集型任务,并且必须等待完成.相反地,我们进行任务调度,我们将一个任务封装成一个消息,并将其发送到队列.工作进行在后台运行不断的从队列中取出任务然后执 ...

  8. 物联网学习笔记三:物联网网关协议比较:MQTT 和 Modbus

    物联网学习笔记三:物联网网关协议比较:MQTT 和 Modbus 物联网 (IoT) 不只是新技术,还是与旧技术的集成,其关键在于通信.可用的通信方法各不相同,但是,各种不同的协议在将海量“事物”连接 ...

  9. 官网英文版学习——RabbitMQ学习笔记(十)RabbitMQ集群

    在第二节我们进行了RabbitMQ的安装,现在我们就RabbitMQ进行集群的搭建进行学习,参考官网地址是:http://www.rabbitmq.com/clustering.html 首先我们来看 ...

随机推荐

  1. cmd执行调用打开文件

    Process p = new Process();//新进程 p.StartInfo.FileName = "cmd.exe";//打开cmd程序 p.StartInfo.Use ...

  2. VS2013+ffmpeg开发环境搭建-->【转】

    本文转载自:http://blog.csdn.net/qq_28425595/article/details/51488869 版权声明:本文为博主原创文章,未经博主允许不得转载. 今天整理资料时,发 ...

  3. Dijkstra算法原理及证明(转)

    Dijkstra算法及其证明 算法: 设G是带权图,图中的顶点多于一个,且所有的权都为正数.本算法确定从顶点S到G中其他各个顶点的距离和最短通路.在本算法中P表示带永久标记的顶点的集合.顶点A的前驱是 ...

  4. js设计模式-工厂模式(XHR工厂)

    场景:如果代码中需要多次执行Ajax请求,那么明智的做法是把创建这种对象的代码提取到一个类中,并创建一个包装器来包装在实际请求时所要经历的一系列步骤.简单工厂非常适合这种场合. /*AjaxHandl ...

  5. 什么是CAS?

    CAS(Compare-and-Swap),即比较并替换,是一种实现并发算法时常用到的技术,Java并发包中的很多类都使用了CAS技术.CAS需要有3个操作数:内存地址V,旧的预期值A,即将要更新的目 ...

  6. nginx配置访问密码,让用户输入用户名密码才能访问

    如果我们在 nginx 下搭建了一些站点,但是由于站点内容或者流量的关系,我们并不想让所有人都能正常访问,那么我们可以设置访问认证.只有让用户输入正确的用户名和密码才能正常访问.效果如下: 在 ngi ...

  7. Hadoop MapReduce编程 API入门系列之wordcount版本3(七)

    这篇博客,给大家,体会不一样的版本编程. 代码 package zhouls.bigdata.myMapReduce.wordcount3; import java.io.IOException; i ...

  8. (转)(C++)关于抽象基类和纯虚函数

    ★抽象类:一个类可以抽象出不同的对象来表达一个抽象的概念和通用的接口,这个类不能实例化(创造)对象. ★纯虚函数(pure virtual):在本类里不能有实现(描述功能),实现需要在子类中实现.例: ...

  9. Gitlab 维护措施

    Gitlab 升级: https://jingyan.baidu.com/article/72ee561ab1b333e16038df63.html Gitlab Rpm包地址: https://pa ...

  10. hiho一下 第174周

    题目1 : Dice Possibility 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 What is possibility of rolling N dice ...