rabbitMQ学习笔记(三) 消息确认与公平调度消费者
从本节开始称Sender为生产者 , Recv为消费者
一、消息确认
为了确保消息一定被消费者处理,rabbitMQ提供了消息确认功能,就是在消费者处理完任务之后,就给服务器一个回馈,服务器就会将该消息删除,如果消费者超时不回馈,那么服务器将就将该消息重新发送给其他消费者
默认是开启的,在消费者端通过下面的方式开启消息确认, 首先将autoAck自动确认关闭,等我们的任务执行完成之后,手动的去确认,类似JDBC的autocommit一样
QueueingConsumer consumer = new QueueingConsumer(channel);
boolean autoAck = false;
channel.basicConsume("hello", autoAck, consumer);
在前面的例子中使用的是channel.basicConsume(channelName, true, consumer) ; 在接收到消息后,就会自动反馈一个消息给服务器。
下面这个例子来测试消息确认的功能。
Sender03.java
package com.zf.rabbitmq03; import java.io.IOException; import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory; /**
* 发送消息
* @author zhoufeng
*
*/
public class Sender03 { public static void main(String[] args) throws IOException { ConnectionFactory connFac = new ConnectionFactory() ; //RabbitMQ-Server安装在本机,所以直接用127.0.0.1
connFac.setHost("127.0.0.1"); //创建一个连接
Connection conn = connFac.newConnection() ; //创建一个渠道
Channel channel = conn.createChannel() ; //定义Queue名称
String queueName = "queue01" ; //为channel定义queue的属性,queueName为Queue名称
channel.queueDeclare( queueName , false, false, false, null) ; String msg = "Hello World!"; //发送消息
channel.basicPublish("", queueName , null , msg.getBytes()); System.out.println("send message[" + msg + "] to "+ queueName +" success!"); channel.close();
conn.close(); } }
与Sender01.java一样,没有什么区别。
Recv03.java
package com.zf.rabbitmq03; import java.io.IOException; import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.ConsumerCancelledException;
import com.rabbitmq.client.QueueingConsumer;
import com.rabbitmq.client.QueueingConsumer.Delivery;
import com.rabbitmq.client.ShutdownSignalException; /**
* 接收消息
* @author zhoufeng
*
*/
public class Recv03 { public static void main(String[] args) throws IOException, ShutdownSignalException, ConsumerCancelledException, InterruptedException { ConnectionFactory connFac = new ConnectionFactory() ; connFac.setHost("127.0.0.1"); Connection conn = connFac.newConnection() ; Channel channel = conn.createChannel() ; String channelName = "channel01"; channel.queueDeclare(channelName, false, false, false, null) ; //配置好获取消息的方式
QueueingConsumer consumer = new QueueingConsumer(channel) ; //取消 autoAck
boolean autoAck = false ; channel.basicConsume(channelName, autoAck, consumer) ; //循环获取消息
while(true){ //获取消息,如果没有消息,这一步将会一直阻塞
Delivery delivery = consumer.nextDelivery() ; String msg = new String(delivery.getBody()) ; //确认消息,已经收到
channel.basicAck(delivery.getEnvelope().getDeliveryTag()
, false); System.out.println("received message[" + msg + "] from " + channelName);
} } }
注意:一旦将autoAck关闭之后,一定要记得处理完消息之后,向服务器确认消息。否则服务器将会一直转发该消息
如果将上面的channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);注释掉, Sender03.java只需要运行一次 , Recv03.java每次运行将都会收到HelloWorld消息
注意:
但是这样还是不够的,如果rabbitMQ-Server突然挂掉了,那么还没有被读取的消息还是会丢失 ,所以我们可以让消息持久化。 只需要在定义Queue时,设置持久化消息就可以了,方法如下:
boolean durable = true;
channel.queueDeclare(channelName, durable, false, false, null);
这样设置之后,服务器收到消息后就会立刻将消息写入到硬盘,就可以防止突然服务器挂掉,而引起的数据丢失了。 但是服务器如果刚收到消息,还没来得及写入到硬盘,就挂掉了,这样还是无法避免消息的丢失。
二、公平调度
上一个例子能够实现发送一个Message与接收一个Message
从上一个Recv01中可以看出,必须处理完一个消息,才会去接收下一个消息。如果生产者众多,那么一个消费者肯定是忙不过来的。此时就可以用多个消费者来对同一个Channel的消息进行处理,并且要公平的分配任务给多个消费者。不能部分很忙 部分总是空闲
实现公平调度的方式就是让每个消费者在同一时刻会分配一个任务。 通过channel.basicQos(1);可以设置
rabbitMQ学习笔记(三) 消息确认与公平调度消费者的更多相关文章
- RabbitMQ 消息确认与公平调度消费者
一.消息确认 为了确保消息一定被消费者处理,rabbitMQ提供了消息确认功能,就是在消费者处理完任务之后,就给服务器一个回馈,服务器就会将该消息删除,如果消费者超时不回馈,那么服务器将就将该消息重新 ...
- rabbitMQ学习笔记(五) 消息路由
生产者会生产出很多消息 , 但是不同的消费者可能会有不同的需求,只需要接收指定的消息,其他的消息需要被过滤掉. 这时候就可以对消息进行过滤了. 在消费者端设置好需要接收的消息类型. 如果不使用默认的E ...
- Linux内核学习笔记(7)--完全公平调度(CFS)
一.完全公平调度算法 完全公平调度 CFS 的出发点基于一个简单的理念:进程调度的效果应该如同系统具备一个理想中的完美多任务处理器.在这种系统中,每个进程能够获得 1/n 的处理器时间(n 为可运行进 ...
- RabbitMQ学习笔记三:Java实现RabbitMQ之与Spring集成
搭建好maven项目环境,加入RabbitMQ依赖包 <dependency> <groupId>org.springframework.amqp</groupId> ...
- RabbitMQ学习笔记五:RabbitMQ之优先级消息队列
RabbitMQ优先级队列注意点: 1.只有当消费者不足,不能及时进行消费的情况下,优先级队列才会生效 2.RabbitMQ3.5以后才支持优先级队列 代码在博客:RabbitMQ学习笔记三:Java ...
- RabbitMQ学习系列三-C#代码接收处理消息
RabbitMQ学习系列三:.net 环境下 C#代码订阅 RabbitMQ 消息并处理 http://www.80iter.com/blog/1438251320680361 http://www. ...
- rabbitmq学习(三) —— 工作队列
工作队列,又称任务队列,主要思想是避免立即执行资源密集型任务,并且必须等待完成.相反地,我们进行任务调度,我们将一个任务封装成一个消息,并将其发送到队列.工作进行在后台运行不断的从队列中取出任务然后执 ...
- 物联网学习笔记三:物联网网关协议比较:MQTT 和 Modbus
物联网学习笔记三:物联网网关协议比较:MQTT 和 Modbus 物联网 (IoT) 不只是新技术,还是与旧技术的集成,其关键在于通信.可用的通信方法各不相同,但是,各种不同的协议在将海量“事物”连接 ...
- 官网英文版学习——RabbitMQ学习笔记(十)RabbitMQ集群
在第二节我们进行了RabbitMQ的安装,现在我们就RabbitMQ进行集群的搭建进行学习,参考官网地址是:http://www.rabbitmq.com/clustering.html 首先我们来看 ...
随机推荐
- [iOS]UITableViewController完毕收回键盘操作
UITableViewController 本身可以实现键盘适配(cell中控件焦点会移动到键盘上方 在做键盘收回的时候思考过例如以下方案 1.tableview加入点击事件 结果:点击事件和tabl ...
- android 构建GPS Provide步骤及信息
构建GPS Provide步骤及信息 1. 用GPS2GoogleEarth录制KML文件 2. KML文件 2.1 经纬度解析 <LineString> <coordina ...
- 2016.04.06,英语,《Vocabulary Builder》Unit 10
put, from the Latin verb putare, meaning 'to think, consider, or believe'. reputation: [ˌrepju'teɪʃn ...
- Ubuntu16.04系统下汉字显示为方框解决办法(图文详解)
不多说,直接上干货! 问题详情 问题分析 今天一打开Ubuntu系统,竟然不支持中文显示了.开始时以为是搜狗拼音的问题,然后重装了一遍fcitx,然后用重装了一遍搜狗输入法.可是重装后问题根本没有解决 ...
- jQuery基本选择器模块(二)
选择器模块 1.push方法的兼容性(了解) 问题:IE8不支持aplly方法中的第二个参数是 伪数组 目标:实现 push 方法的浏览器兼容性问题 var push = [].push; try { ...
- Singleton pattern的线程安全问题
original post from here方法一:同步机制关键词public class Singleton { 2 //利用静态变量来记录Singleton的唯一实例 3 private sta ...
- outlook 2010 搜索不到邮件
打开outlook 2010 文件, 选项, 加载项, 转到 windows search eamil indexer(打勾) 关闭outlook 控制面板, 索引选项, 高级, 重建索引
- React 学习笔记:1-react 入门
接下来的项目里有用到react,最近一段时间主要关注于react 的学习.大部门都是网上的资料,学习整理并记录,加深记忆. React 是Facebook推出的用来构建用户界面的JavaScript库 ...
- 03--(二)编程实践中C语言的一些常见细节
编程实践中C语言的一些常见细节(转载) 对于C语言,不同的编译器采用了不同的实现,并且在不同平台上表现也不同.脱离具体环境探讨C的细节行为是没有意义的,以下是我所使用的环境,大部分内容都经过测试,且所 ...
- CSV文件模块的使用
---恢复内容开始--- 1.CSV模块使用流程 1.导入模块 impport CSV 2.打开文件(xxx.csv) with open('xxx.csv','a',encoding='utf-8' ...