一、JMS消息结构(Message)

Message主要由三部分组成,分别是Header,Properties,Body, 详细如下:

Header 消息头,所有类型的这部分格式都是一样的
Properties 属性,按类型可以分为应用设置的属性,标准属性和消息中间件定义的属性
Body 消息正文,指我们具体需要消息传输的内容。

1.1 Header

JMS消息头使用的所有方法:

public interface Message {public Destination getJMSDestination() throws JMSException;public void setJMSDestination(Destination destination) throws JMSException;public int getJMSDeliveryMode() throws JMSExceptionpublic void setJMSDeliveryMode(int deliveryMode) throws JMSException;public String getJMSMessageID() throws JMSException;public void setJMSMessageID(String id) throws JMSException;public long getJMSTimestamp() throws JMSException'public void setJMSTimestamp(long timestamp) throws JMSException;public long getJMSExpiration() throws JMSException;public void setJMSExpiration(long expiration) throws JMSException;public boolean getJMSRedelivered() throws JMSException;public void setJMSRedelivered(boolean redelivered) throws JMSException;public int getJMSPriority() throws JMSException;public void setJMSPriority(int priority) throws JMSException;public Destination getJMSReplyTo() throws JMSException;public void setJMSReplyTo(Destination replyTo) throws JMSException;public String getJMScorrelationID() throws JMSException;public void setJMSCorrelationID(String correlationID) throws JMSException;public byte[] getJMSCorrelationIDAsBytes() throws JMSException;public void setJMSCorrelationIDAsBytes(byte[] correlationID) throws JMSException;public String getJMSType() throws JMSException;public void setJMSType(String type) throws JMSException;
}

消息头分为自动设置和手动设置的内容。

1.1.1 自动头信息

有一部分可以在创建Session和MessageProducer时设置

属性名称 说明 设置者
JMSDeliveryMode 消息的发送模式,分为NON_PERSISTENTPERSISTENT,即非持久性模式的和持久性模式。默认设置为PERSISTENT(持久性)。一条持久性消息应该被传送一次(就一次),这就意味着如果JMS提供者出现故障,该消息并不会丢失; 它会在服务器恢复正常之后再次传送。一条非持久性消息最多只会传送一次,这意味着如果JMS提供者出现故障,该消息可能会永久丢失。在持久性和非持久性这两种传送模式中,消息服务器都不会将一条消息向同一消息者发送一次以上(成功算一次)。 send
JMSMessageID 消息ID,需要以ID:开头,用于唯一地标识了一条消息 send
JMSTimestamp 消息发送时的时间。这条消息头用于确定发送消息和它被消费者实际接收的时间间隔。时间戳是一个以毫秒来计算的Long类型时间值(自1970年1月1日算起)。 send
JMSExpiration 消息的过期时间,以毫秒为单位,用来防止把过期的消息传送给消费者。任何直接通过编程方式来调用setJMSExpiration()方法都会被忽略。 send
JMSRedelivered 消息是否重复发送过,如果该消息之前发送过,那么这个属性的值需要被设置为true, 客户端可以根据这个属性的值来确认这个消息是否重复发送过,以避免重复处理。 Provider
JMSPriority 消息的优先级,0-4为普通的优化级,而5-9为高优先级,通常情况下,高优化级的消息需要优先发送。任何直接通过编程方式调用setJMSPriority()方法都将被忽略。 send
JMSDestination 消息发送的目的地,是一个Topic或Queue send

JMSDeliveryMode  :

MessageProducer producer = session.createProducer(topic);
producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);

JMSExpiration:

//将过期时间设置为1小时(1000毫秒 *60 *60)
producer.setTimeToLive(1000 * 60 * 60);

JMSPriority

producer.setPriority(9);

1.1.2 手动头信息

属性名称 说明 设置者
JMSCorrelationID 关联的消息ID,这个通常用在需要回传消息的时候 client
JMSReplyTo 消息回复的目的地,其值为一个Topic或Queue, 这个由发送者设置,但是接收者可以决定是否响应 client
JMSType 由消息发送者设置的消息类型,代表消息的结构,有的消息中间件可能会用到这个,但这个并不是是批消息的种类,比如TextMessage之类的 client

从上表中我们可以看到,系统提供的标准头信息一共有10个属性,其中有6个是由send方法在调用时设置的,有三个是由客户端(client)设置的,还有一个是由消息中间件(Provider)设置的。

二、下一代 ActiveMQ 6?Artemis

为下一代事件驱动的消息传递应用程序提供高性能、无阻塞的体系结构。

  • 包含JNDI,具有完整的JMS 1.1 & 2.0客户端实现
  • 高可用性共享存储、网络复制能力
  • 简单而强大的寻址模型协议
  • 灵活的负载均衡分配能力
  • 针对低延迟持久性和JDBC的高级日志实现
  • 与ActiveMQ 5的高功能奇偶校验,以简化迁移

官方文档:ActiveMQ

  • netty
  • 自己的存储
  • 优化传输流程
  • 更高的性能
  • 不再把所有的协议转换成openwire

提升服务器性能可以在发送端:

把tcp://localhost:61616 改为 nio://localhost:61616

三、高级使用

3.1 JMSCorrelationID

用于消息之间的关联,给人一种会话的感觉3.2

3.2 JMSReplyTo

发送方可以接受到消息消费确认的地址。

ActiveMQ5.10.x 以上版本必须使用 JDK1.8 才能正常使用。

ActiveMQ5.9.x 及以下版本使用 JDK1.7 即可正常使用。

可以查看下面链接进行了解:

ActiveMQ之JMSReplyTo - 技无止境 - 博客园

四、面试题

4.1 ActiveMQ如何防止消息丢失?会不会丢消息?

4.4.1 会不会丢消息:

取决于消息的类型以及producer和broker设置的属性。如果消息不是持久化的,那么在producer发送完消息后,broker当时在线,comsumer没在线,那消息还停留在broker里,这时候如果broker宕机,comsumer和broker同时上线,那么消息就丢了。
本质上activemq啊,kafka啊,rocketmq等,没有特别改配置的话,一般都不会丢消息,丢消息就是出了问题。
如果消息systemUsage设置不合理,或者说消息多到已经满了,那么producer再发送消息,broker也接收不了,这时候就要考虑集群了,高可用(主从节点)和高性能(消息分片)集群。后面我们再考虑。

systemUsage设置:

4.1.2 防止丢消息:

  1. 死信队列。当消息过期了,这条消息会被activemq转发到死信队列里。
  2. ReplyTo。同时我们要保证消息系统的健壮性,发消息的时候要关注 ReplyTo,ReplyTo也能保证消息一定能让对方收到,如果一直没有收到消费者的消息确认的话,那么这会儿可能也出问题了。ReplyTo言简意赅的解释就是comsumer收到消息都给producer一个确认。
  3. 持久化,一定要做。除非是要求极高性能的情况下。如果要求broker宕机后,消息还有,持久化一定要做!持久化做了的话,一定会影响性能,因为它是同步写入的,每一条都会写入到kahadb,写完之后才会告诉producer消息已发出。
  4. ack,相当于确认消息收到了。消息收到之后,ack一下,就不会重复投递了,同时会在持久化消息里把这条消息删掉。
  5. 消息重投。设置消息重投,多投几遍,总没有坏处,因为网络是最不可靠的因素。在cap定理里,p就主要代表网络的不稳定。
  6. 记录日志。记录日志是指发了一条消息不止是activemq的持久化,还记录日志(或者存到数据库),以便溯源和审计。
  7. 独占消费者。 ActiveMQ从4.x版本起开始支持Exclusive Consumer (或者说Exclusive Queues)。消费端设置了独占消息,Broker会从多个consumers中挑选一个consumer来处理queue中所有的消息,从而保证了消息的有序处理。如果这个consumer失效,那么broker会自动切换到其它的consumer。

    所以有时候要查看一下是否设置了独占消费者。https://blog.csdn.net/ywl470812087/article/details/84702137

  8. broker负载/限流。
    负载:如果broker设置了负载,有可能消息被负载到别的broker上了。
    限流是说,broker设置了最大接受内存,当再有消息发送过来,broker也不会接了。

4.1.3 如何防止重复消费?

消息幂等处理

map ConcurrentHashMap -> putIfAbsent guava cache

思路:

客户端用ConcurrentHashMap.putIfAbsent (消息id,1)先用存放消息id。

putIfAbsent方法主要是在向ConcurrentHashMap中添加键—值对的时候,它会先判断该键值对是否已经存在。

  • 如果不存在(新的entry),那么会向map中添加该键值对,并返回null。
  • 如果已经存在,那么不会覆盖已有的值,直接返回已经存在的值。

所以可以根据返回值是不是null,来判断目前的消息是否已被消费过。

guava cache的api:

 /*** 10分钟自动过期*/Cache<String, String>  cache = CacheBuilder.newBuilder().expireAfterWrite(60*10, TimeUnit.SECONDS).build();

ActiveMQ(三)——JMS消息结构、JMSReplyTo、面试题(消息丢失,消息重复,消息顺序)相关推荐

  1. MQ 消息丢失、重复、积压问题,如何解决?

    面试官在面试候选人时,如果发现候选人的简历中写了在项目中使用了 MQ 技术(如 Kafka.RabbitMQ.RocketMQ),基本都会抛出一个问题:在使用 MQ 的时候,怎么确保消息 100% 不 ...

  2. RabbitMQ常见问题解决方案——消息丢失、重复消费、消费乱序、消息积压

    文章目录 背景 RabbitMQ常见问题解决方案 1. RabbitMQ的可靠性(消息丢失问题) 1.1 生产者丢失消息 1.2 RabbitMQ弄丢消息 1.2.1 交换机持久化 1.2.2 队列持 ...

  3. 消息队列面试连环问:如何保证消息不丢失?处理重复消息?消息有序性?消息堆积处理?...

    大家好,我是 yes. 最近我一直扎在消息队列实现细节之中无法自拔,已经写了 3 篇Kafka源码分析,还剩很多没肝完.之前还存着RocketMQ源码分析还没整理.今儿暂时先跳出来盘一盘大方向上的消息 ...

  4. ActiveMQ入门 (三) JMS消息组成

    ActiveMQ入门 (三) JMS消息组成 文章目录 ActiveMQ入门 (三) JMS消息组成 一.JMS协议组成结构 二.JMS Message消息组成 1.JMS消息头 2.JMS消息体 1 ...

  5. 框架面试题(maven、ZooKeeper、Dubbo、Nginx、Redis、Lucene、Solr、ActiveMQ、JMS

    什么是 Maven? Maven 使用项目对象模型(POM)的概念,可以通过一小段描述信息来管理项目的构建, 报告和文档的软件项目管理工具. Maven 除了以程序构建能力为特色之外,还提供高级项目管 ...

  6. mq服务器与客户端消息同步,使用 ActiveMQ 实现JMS 异步调用

    目录 简介 服务之间的同步调用,可以使用 HTTP 或 RPC 来完成,但并非所有的调用都需要同步,有些场景下,当客户端调用服务端时,并不需要等待服务端做出响应,此时就应该使用异步调用.异步调用的常用 ...

  7. java tomcat jms_JavaWeb之使用Tomcat、JNDI与ActiveMQ实现JMS消息通信服务

    前言 之所以使用JNDI 是出于通用性考虑,该例子使用JMS规范提供的通用接口,没有使用具体JMS提供者的接口,这样可以保证我们编写的程序适用于任何一种JMS实现(ActiveMQ.HornetQ等) ...

  8. 【ActiveMQ】JMS中间件ActiveMQ详解

    1.JMS介绍 Java Message Service(JMS)是SUN提出的旨在统一各种MOM(Message-Oriented Middleware )系统接口的规范,它包含点对点(Point ...

  9. RabbitMQ消息队列常见面试题总结

    1.什么是消息队列: 1.1.消息队列的优点: (1)解耦:将系统按照不同的业务功能拆分出来,消息生产者只管把消息发布到 MQ 中而不用管谁来取,消息消费者只管从 MQ 中取消息而不管是谁发布的.消息 ...

  10. Java消息服务~JMSReplyTo示例

    在下面的例子中,首先创建两个Queue,发送者给一个Queue发送,接收者接收到消息之后给另一个Queue回复一个Message,然后再创建一个消费者来接受所回复的消息 import javax.jm ...

最新文章

  1. 微信硬件平台智能路由行业解决方案
  2. 让DB2数据库更牢靠
  3. Warning: Multiple build commands for output file /xxx
  4. 《专门替中国人写的英语语法》(四)
  5. 全国人口净流入城市排名2020_从人口净流入量来看一线城市吸引力的对比分析...
  6. Jmeter使用之高效组织接口自动化用例技巧
  7. nRF24L01模块——基于Arduino
  8. 双光耦开关电源电路图_双路输出回扫式开关电源电路图
  9. xp计算机字体在哪,Windows XP系统字体库在哪-如何安装新字体
  10. 60906磁悬浮动力系统应用研究与模型搭建
  11. IT技术分享的一点点总结
  12. Javascript - The same RegExp behave differently
  13. 倾听社区的声音,但别被他们牵着鼻子走
  14. 知识管理文档协同不一定要用语雀和石墨,用它效果更好
  15. 用esp8266驱动0.96寸OLED屏幕 太空人动画
  16. 共享办公室,月赚2万-5万的阳光创业项目
  17. 智能微电网的核心技术
  18. 哲理故事与管理之道(22)-用竞争激励下属
  19. [rtsp @ 0x55ba1dae9200] UDP timeout, retrying with TCP的解决办法
  20. 【案例分享】高效率利器 - SC 频谱分析仪

热门文章

  1. 推荐系统回顾,FFM引入特征域进一步增强了模型的表达能力。大规模分段线性模型LS-PLM
  2. 平衡二叉树的插入与调整
  3. 多小区下小区上行速率的计算(2)
  4. 电力系统技术导则_《电力系统安全稳定导则(征求意见稿)》发布
  5. SpringBoot中的文件读取
  6. MapReduce如何使用多路输出
  7. 【面向代码】学习 Deep Learning(一)Neural Network
  8. 常用算法之-快速排序
  9. 操作系统课设 Nachos 实验一:Nachos 系统的安装与调试
  10. 使用EDD枚举域数据