消息中间件-activemq消息机制和持久化介绍(三)
前面一节简单学习了activemq的使用,我们知道activemq的使用方式非常简单有如下几个步骤:
- 创建连接工厂
- 创建连接
- 创建会话
- 创建目的地
- 创建生产者或消费者
- 生产或消费消息
- 关闭生产或消费者、关闭会话、关闭连接
前面我们的实例代码中已经按照这个步骤完成了P2P和Pub/Sub模式的消息发送和接收。那么这一节我们就针对他的消息传播机制和持久化方式做一个简单的学习。在会用的同时我们也需要理解一些基本的概念,这样才不至于在出错后无从下手。
1.activemq服务器工作模型
我们先看一下消息发送的时序图:
ConnectionFactory 对象创建一个连接工厂,消息的发送和接受服务均由此进行;
ConnectionFactory 创建一个活动Connection作为当前使用的连接;
Session 是一个用于生成和使用消息的单线程上下文,它用于创建发送的生产者和接收消息的消费者,并为所发送的消息定义发送顺序。会话通过大量确认选项或通过事务来支持可靠传送。
户端使用 MessageProducer 向指定的物理目标发送消息,生产者可指定一个默认传送模式(持久性消息与非持久性消息)、优先级和有效期值,以控制生产者向物理目标发送的所有消息;
消费者可以支持同步或异步消息接收。异步使用可通过向消费者注册 MessageListener 来实现。当会话线程调用 MessageListener 对象的 onMessage 方法时,客户端将使用消息。
2.ActiveMQ消息传送模型
ActiveMQ 支持两种消息传送模型:PTP(即点对点模型)和Pub/Sub(即发布 /订阅模型),前面我们已经讲过,在此就不赘述。
3.消息选择器
ActiveMQ提供了一种机制,使用它,消息服务可根据消息选择器中的标准来执行消息过滤。生产者可在消息中放入应用程序特有的属性,而消费者可使用基于这些属性的选择标准来表明对消息是否感兴趣。
消息选择器是根据 header 和 properties 允许客户端选择性的制定需要接收的消息,消息选择器是无法利用 消息主体(Body)进行过滤的。无论你的消息主题是什么类型, 文本、或者对象、或者键值对。下面我们讲一下消息选择器的语法以及使用规范:
可接收的类型包括:byte,int,double,boolean,String;
属性标识符定义:
变量名与java定义一样;
要么在heads中定义 要么在 properties中定义,如果在sender中是在heads中定义而receiver中却从properties中寻找的话,找不到的情况下他是不会自动去heads中寻找的,而是会返回null;
根据不同类型的变量选择不同的方法:
message.setIntProperty("test",14);
那么在接收端可以对该变量进行拦截:
session.createConsumer(destination,"test > 14");
属性标志符是区分大小写的;
拦截器中的部分表示方式:
可以是条件表达式
可以是算术表达式
可以是比较运算和逻辑运算组成的表达式
支持 () 左右括号;
支持逻辑运算的优先顺序表达式 例如: NOT , AND , OR;
比较运算符有: = , > , >= , < , <= , <> (not equal);
eg:
标识符是null
"prop_name IS NULL"
标识符非空 not null
"prop_name IS NOT NULL"
"age BETWEEN 15 AND 19" is equivalent to "age >= 15 AND age <= 19"
"Country NOT IN (' UK', 'US', 'France') "
代码很简单,只需要在Sender端做如下改写:
TextMessage message = session.createTextMessage();
message.setIntProperty("test",14);
message.setText("test");
Receiver端:
consumer = session.createConsumer(destination,"test > 14");
对发送端的特定字符做一个判断符合条件即被拦截
4.消息确认机制
jms消息只有在被确认之后才认为成功消费了这条消息。消息的成功消费通常包括三个步骤:
(1)client接收消息
(2)client处理消息
(3)消息被确认(也就是client给一个确认消息)
在事务性会话中当一个事务被提交的时候,确认自动发生,和应答模式没关系,这个值可以随便写。(这里多提一句异步消息接收中不能使用事务性会话)。
在非事务性会话中消息何时被确认取决于创建的session中设置的消息应答模式(acknowledge model)该参数有三个值:
- Session.AUTO_ACKNOWLEDGE:当client端成功的从receive方法或从onMessage(Message message) 方法返回的时候,会话自动确认client收到消息。
- Session.CLIENT_ACKNOWLEDGE: 客户单通过调用acknowledge方法来确认客户端收到消息。但需要注意在这种应答模式下,确认是在会话层上进行的,确认一个被消费的消息将自动确认所有已消费的其他消息。比如一个消费者已经消费了10条消息,然后确认了第5条消息被消费,则这10条都被确认消费了。、
acknowledge()通知方法是在Message对象上,同步接收,调用acknowledge()方法进行确认如下所示:
consumer = session.createConsumer(queue);
Message message = consumer.receive();
message.acknowledge();
异步接受,调用acknowledge()方法进行确认:
consumer.setMessageListener(new MessageListener() {
@Override
public void onMessage(Message message) {
TextMessage textMessage = (TextMessage) message;
try {
String value = textMessage.getText();
System.out.println("value: " + value);
message.acknowledge(); //消息消费确认通知
} catch (JMSException e) {
e.printStackTrace();
}
}
});
3.Session.DUPS_ACKNOWLEDGE:不是必须签收,消息可能会重复发送。在第二次重新传送消息的时候,消息头的JmsDelivered会被置为true标示当前消息已经传送过一次,客户端需要进行消息的重复处理控制。
5. 持久化消息
JMS 支持以下两种消息提交模式:
5.1 ERSISTENT 持久消息
是activemq默认的传送方式,此方式下的消息在配合activemq.xml中配置的消息存储方式,会被存储在特定的地方,直到有消费者将消息消费或者消息过期进入DLQ队列,消息生命周期才会结束。此模式下可以保证消息只会被成功传送一次和成功使用一次,消息具有可靠性。在消息传递到目标消费者,在消费者没有成功应答前,消息不会丢失。所以很自然的,需要一个地方来持久性存储。如果消息消费者在进行消费过程发生失败,则消息会被再次投递。
DeliveryMode.PERSISTENT 指示JMS provider持久保存消息,以保证消息不会因为JMS provider的失败而丢失。 消息持久化在硬盘中,ActiveMQ持久化有三种方式:AMQ、KahaDB、JDBC。
AMQ
AMQ是一种文件存储形式,它具有写入速度快和容易恢复的特点。消息存储在一个个文件中,文件的默认大小为32M,如果一条消息的大小超过了32M,那么这个值必须设置大一点。当一个存储文件中的消息已经全部被消费,那么这个文件将被标识为可删除,在下一个清除阶段,这个文件被删除。AMQ适用于ActiveMQ5.3之前的版本。
KahaDB
KahaDB是基于文件的本地数据库储存形式,虽然没有AMQ的速度快,但是它具有强扩展性,恢复的时间比AMQ短,从5.4版本之后KahaDB做为默认的持久化方式。
JDBC
可以将消息存储到数据库中,例如:Mysql、SQL Server、Oracle、DB2。
具体使用方式大家下去查一下,限于篇幅在此就不做太详细的介绍。
5.2 NON_PERSISTENT 非持久消息
非持久的消息适用于不重要的,可以接受消息丢失的哪一类消息,这种消息只会被投递一次,消息不会在持久性存储中存储,也不会保证消息丢失后的重新投递。
DeliveryMode.NON_PERSISTENT 不要求JMS provider持久保存消息,消息存放在内存中,读写速度快,在JMS服务停止后消息会消失,没有持久化到硬盘。
6. ActiveMQ消息过期设置
允许消息过期 。默认情况下,消息永不会过期。如果消息在特定周期内失去意义,那么可以设置过期时间。
有两种方法设置消息的过期时间,时间单位为毫秒:
- 使用 setTimeToLive 方法为所有的消息设置过期时间;
- 使用 send 方法为每一条消息设置过期时间。
消息过期时间,send 方法中的 timeToLive 值加上发送时刻的 GMT 时间值。如果 timeToLive 值等于零,则 JMSExpiration 被设为零,表示该消息永不过期。如果发送后,在消息过期时间之后消息还没有被发送到目的地,则该消息被清除。
这一节对activemq的消息机制和持久化我们就简单介绍到这里,后面我们结合具体的工程来把它应用到生产中,再来讲解如何持久化如何高效的应用于生产环境。
消息中间件-activemq消息机制和持久化介绍(三)的更多相关文章
- 消息中间件-activemq安全机制
activemq作为消息中间件这样一个独立的个体存在,连通用户和服务器.如果没有一套完备的安全机制去设置用户权限设置消息分发机制可想后果是非常严重.ActiveMQ如果不加入安全机制的话,任何人只要知 ...
- 消息中间件-activemq实战之消息持久化(六)
对于activemq消息的持久化我们在第二节的时候就简单介绍过,今天我们详细的来分析一下activemq的持久化过程以及持久化插件.在生产环境中为确保消息的可靠性,我们肯定的面临持久化消息的问题,今天 ...
- Springboot+ActiveMQ(ActiveMQ消息持久化,保证JMS的可靠性,消费者幂等性)
ActiveMQ 持久化设置: 在redis中提供了两种持久化机制:RDB和AOF 两种持久化方式,避免redis宕机以后,能数据恢复,所以持久化的功能 对高可用程序来说 很重要. 同样在Active ...
- Kafka分片存储、消息分发和持久化机制
Kafka 分片存储机制 Broker:消息中间件处理结点,一个 Kafka 节点就是一个 broker,多个 broker 可以组成一个 Kafka集群. Topic:一类消息,例如 page vi ...
- ActiveMQ基础教程(三):C#连接使用ActiveMQ消息队列
接上一篇:ActiveMQ基础教程(二):安装与配置(单机与集群) 安装部署好集群环境:192.168.209.133:61616,192.168.209.134:61616,192.168.209. ...
- ActiveMQ消息的可靠性机制(转)
文章转自:http://www.linuxidc.com/Linux/2013-02/79664.htm 1.JMS消息确认机制 JMS消息只有在被确认之后,才认为已经被成功地消费了.消息的成功消费通 ...
- 学习ActiveMQ(八):activemq消息的持久化
1. 持久化方式介绍前面我们也简单提到了activemq提供的插件式的消息存储,在这里再提一下,主要有以下几种方式: AMQ消息存储-基于文件的存储方式,是activemq开始的版本默认的消息存储方式 ...
- Activemq消息确认机制 --转载
转自:http://blog.csdn.net/czp11210/article/details/47022639 ActiveMQ消息传送机制以及ACK机制详解 AcitveMQ是作为一种消息存 ...
- 快速掌握RabbitMQ(三)——消息确认、持久化、优先级的C#实现
1 消息确认 在一些场合,如转账.付费时每一条消息都必须保证成功的被处理.AMQP是金融级的消息队列协议,有很高的可靠性,这里介绍在使用RabbitMQ时怎么保证消息被成功处理的.消息确认可以分为两种 ...
随机推荐
- strcpy strlen 实现
1. strcpy:字符串拷贝函数,无边界,一直拷贝到字符串结束符 '\0' 为止. char* strcpy(char* strDest, const char* strSrc); 代码实现: #i ...
- 站在巨人的肩膀上看Servlet——原来如此(更适合初学者认识Servlet)
前言: 有段时间没更新博客了,这段时间因为要准备考试,考完试后又忙了一阵别的事,一直没能静下心来写博客.大学考试真是越来越恶心了,各种心酸,那酸爽,够味.不过还好,马上就要大三了,听大三学长学姐说大三 ...
- Java实现LRU算法
一.LRU算法简介 LRU(Least Recently Used)最近最久未使用算法 常见应用场景:内存管理中的页面置换算法.缓存淘汰中的淘汰策略等 二.实现理论 底层结构:双向链表 + HashM ...
- 论文阅读 <Relocalization, Global Optimization and Map Merging for Monocular Visual-Inertial SLAM>
看了一下港科的基于vins拓展的论文<relocalization, global optimization and merging for vins>,在回环的实现部分总体没有什么变化, ...
- 剑指offer第二版-3.数组中重复的数
面试题3:数组中重复的数 题目要求: 在一个长度为n的数组中,所有数字的取值范围都在[0,n-1],但不知道有几个数字重复或重复几次,找出其中任意一个重复的数字. 解法比较: /** * Copyri ...
- 每周一个js重要概念之一 调用堆栈
js写了也有两年多了,大到复杂的后台系统,小到页面,还有日均300万的网页主站,HTML5的适配页面等等. 框架也杂七杂八接触了不少,从小的jquery.bootstrap.echarts等等,到大一 ...
- MySQL常见操作指令
1:使用SHOW语句找出在服务器上当前存在什么数据库: mysql> SHOW DATABASES; 2:创建一个数据库MYSQLDATA mysql> CREATE DATABASE M ...
- The Summer Training Summary-- the first
The Summer Training Summary-- the first A - vector的使用 UVa 101 关于vector 的几个注意点 vector p p.push_back() ...
- Linux运维跳槽必备
Linux运维跳槽必备的40道面试精华题 1.什么是运维?什么是游戏运维?1)运维是指大型组织已经建立好的网络软硬件的维护,就是要保证业务的上线与运作的正常, 在他运转的过程中,对他进行维护,他集合了 ...
- nginx解析漏洞复现
nginx解析漏洞复现 一.漏洞描述 该漏洞与nginx.php版本无关,属于用户配置不当造成的解析漏洞 二.漏洞原理 1. 由于nginx.conf的如下配置导致nginx把以’.php’结尾的文件 ...