activemq

一、 JMS

在介绍ActiveMQ之前,首先简要介绍一下JMS规范。

1.1 JMS的基本构件

1.1.1 连接工厂

连接工厂是客户用来创建连接的对象,例如ActiveMQ提供的ActiveMQConnectionFactory。

如一下代码:

    @Bean
    public ActiveMQConnectionFactory connectionFactory() {
        return new ActiveMQConnectionFactory(usrName, password, brokerUrl);
    }

1.1.2 连接

JMS Connection封装了客户与JMS提供者之间的一个虚拟的连接。


1.1.3 会话

JMS Session是生产和消费消息的一个单线程上下文。会话用于创建消息生产者(producer)、消息消费者(consumer)和消息(message)等。

会话提供了一个事务性的上下文,在这个上下文中,一组发送和接收被组合到了一个原子操作中。

1.1.4 目的地

目的地是客户用来指定它生产的消息的目标和它消费的消息的来源的对象。

JMS1.0.2规范中定义了两种消息传递域:

点对点(PTP)消息传递域和发布/订阅消息传递域。

在点对点消息传递域中,目的地被成为队列(queue);在发布/订阅消息传递域中,目的地被成为主题(topic)。

点对点消息传递域的特点如下:

• 每个消息只能有一个消费者。
• 消息的生产者和消费者之间没有时间上的相关性。无论消费者在生产者发送消息的时候是否处于运行状态,它都可以提取消息。


发布/订阅消息传递域的特点如下:


• 每个消息可以有多个消费者。
• 生产者和消费者之间有时间上的相关性。订阅一个主题的消费者只能消费自它订阅之后发布的消息。JMS规范允许客户创建持久订阅,这在一定程度上放松了时间上的相关性要求。持久订阅允许消费者消费它在未处于激活状态时发送的消息。

 1.1.5 消息生产者

消息生产者是由会话创建的一个对象,用于把消息发送到一个目的地。

1.1.6 消息消费者

消息消费者是由会话创建的一个对象,它用于接收发送到目的地的消息。消息的消费可以采用以下两种方法之一:


• 同步消费。通过调用消费者的receive方法从目的地中显式提取消息。receive方法可以一直阻塞到消息到达。
• 异步消费。客户可以为消费者注册一个消息监听器,以定义在消息到达时所采取的动作。

1.1.7 消息

JMS消息由以下三部分组成的:
• 消息头。每个消息头字段都有相应的getter和setter方法。
• 消息属性。如果需要除消息头字段以外的值,那么可以使用消息属性。
• 消息体。JMS定义的消息类型有TextMessage、MapMessage、BytesMessage、StreamMessage和ObjectMessage。


1.2JMS的可靠性机制

1.2.1 确认JMS消息

只有在被确认之后,才认为已经被成功地消费了。消息的成功消费通常包含三个阶段:

客户接收消息、客户处理消息和消息被确认。

在事务性会话中,当一个事务被提交的时候,确认自动发生。在非事务性会话中,消息何时被确认取决于创建会话时的应答模式(acknowledgement mode)。

该参数有以下三个可选值:
• Session.AUTO_ACKNOWLEDGE。当客户成功的从receive方法返回的时候,或者从MessageListener.onMessage方法成功返回的时候,会话自动确认客户收到的消息。


• Session.CLIENT_ACKNOWLEDGE。客户通过消息的acknowledge方法确认消息。需要注意的是,在这种模式中,确认是在会话层上进行:确认一个被消费的消息将自动确认所有已被会话消费的消息。例如,如果一个消息消费者消费了10个消息,然后确认第5个消息,那么所有10个消息都被确认。


• Session.DUPS_ACKNOWLEDGE。该选择只是会话迟钝的确认消息的提交。如果JMS Provider失败,那么可能会导致一些重复的消息。如果是重复的消息,那么JMS Provider必须把消息头的JMSRedelivered字段设置为true。

1.2.2 持久性

JMS 支持以下两种消息提交模式:
• PERSISTENT。指示JMS Provider持久保存消息,以保证消息不会因为JMS Provider的失败而丢失。
• NON_PERSISTENT。不要求JMS Provider持久保存消息。

1.2.3 优先级

可以使用消息优先级来指示JMS Provider首先提交紧急的消息。优先级分10个级别,从0(最低)到9(最高)。如果不指定优先级,默认级别是4。需要注意的是,JMS Provider并不一定保证按照优先级的顺序提交消息。

1.2.4 消息过期

可以设置消息在一定时间后过期,默认是永不过期。

1.2.5 临时目的地

可以通过会话上的createTemporaryQueue方法和createTemporaryTopic方法来创建临时目的地。它们的存在时间只限于创建它们的连接所保持的时间。只有创建该临时目的地的连接上的消息消费者才能够从临时目的地中提取消息。

1.2.6 持久订阅

首先消息生产者必须使用PERSISTENT提交消息。

客户可以通过会话上的createDurableSubscriber方法来创建一个持久订阅,该方法的第一个参数必须是一个topic,第二个参数是订阅的名称。 JMS Provider会存储发布到持久订阅对应的topic上的消息。如果最初创建持久订阅的客户或者任何其它客户使用相同的连接工厂和连接的客户ID、相同的主题和相同的订阅名再次调用会话上的createDurableSubscriber方法,那么该持久订阅就会被激活。JMS Provider会象客户发送客户处于非激活状态时所发布的消息。 持久订阅在某个时刻只能有一个激活的订阅者。持久订阅在创建之后会一直保留,直到应用程序调用会话上的unsubscribe方法。

1.2.7 本地事务

在一个JMS客户端,可以使用本地事务来组合消息的发送和接收。JMS Session接口提供了commit和rollback方法。事务提交意味着生产的所有消息被发送,消费的所有消息被确认;事务回滚意味着生产的所有消息被销毁,消费的所有消息被恢复并重新提交,除非它们已经过期。

事务性的会话总是牵涉到事务处理中,commit或rollback方法一旦被调用,一个事务就结束了,而另一个事务被开始。关闭事务性会话将回滚其中的事务。 需要注意的是,如果使用请求/回复机制,即发送一个消息,同时希望在同一个事务中等待接收该消息的回复,那么程序将被挂起,因为知道事务提交,发送操作才会真正执行。 需要注意的还有一个,消息的生产和消费不能包含在同一个事务中。

二.ActiveMQ

2.1Broker

ActiveMQ 5.0 的二进制发布包中bin目录中包含一个名为activemq的脚本,直接运行这个脚本就可以启动一个broker。

2.2 Transport

ActiveMQ目前支持的transport有:VM Transport、TCP Transport、SSL Transport、Peer Transport、UDP Transport、Multicast Transport、HTTP and HTTPS Transport、Failover Transport、Fanout Transport、Discovery Transport、ZeroConf Transport等。以下简单介绍其中的几种,更多请参考Apache官方文档。、

2.3 持久化

2.3.1 AMQ Message Store

AMQ Message Store是ActiveMQ5.0缺省的持久化存储。Message commands被保存到transactional journal(由rolling data logs组成)。

Messages被保存到data logs中,同时被reference store进行索引以提高存取速度。Date logs由一些单独的data log文件组成,缺省的文件大小是32M,如果某个消息的大小超过了data log文件的大小,那么可以修改配置以增加data log文件的大小。如果某个data log文件中所有的消息都被成功消费了,那么这个data log文件将会被标记,以便在下一轮的清理中被删除或者归档。

2.4 安全机制

ActiveMQ支持可插拔的安全机制,用以在不同的provider之间切换。

2.5 集群Clustering

ActiveMQ从多种不同的方面提供了集群的支持。

2.5.1 Queue consumer clusters

ActiveMQ支持订阅同一个queue的consumers上的集群。如果一个consumer失效,那么所有未被确认(unacknowledged)的消息都会被发送到这个queue上其它的consumers。如果某个consumer的处理速度比其它consumers更快,那么这个consumer就会消费更多的消息。

2.5.2 Broker clusters

一个常见的场景是有多个JMS broker,有一个客户连接到其中一个broker。如果这个broker失效,那么客户会自动重新连接到其它的broker。在ActiveMQ中使用failover:// 协议来实现这个功能。

2.5.3 Master Slave

在一个网络内运行多个brokers或者standalone brokers时存在一个问题,这就是消息在物理上只被一个broker持有,因此当某个broker失效,那么你只能等待直到它重启后,这个broker上的消息才能够被继续发送(如果没有设置持久化,那么在这种情况下,消息将会丢失)。Master Slave 背后的想法是,消息被复制到slave broker,因此即使master broker遇到了像硬件故障之类的错误,你也可以立即切换到slave broker而不丢失任何消息。 Master Slave是目前ActiveMQ推荐的高可靠性和容错的解决方案

2.6 特性Features

ActiveMQ包含了很多功能强大的特性,下面简要介绍其中的几个。

2.6.1 Exclusive Consumer

Queue中的消息是按照顺序被分发到consumers的。然而,当你有多个consumers同时从相同的queue中提取消息时,你将失去这个保证。因为这些消息是被多个线程并发的处理。有的时候,保证消息按照顺序处理是很重要的。

例如,你可能不希望在插入订单操作结束之前执行更新这个订单的操作。 ActiveMQ从4.x版本起开始支持Exclusive Consumer (或者说Exclusive Queues)。 Broker会从多个consumers中挑选一个consumer来处理queue中所有的消息,从而保证了消息的有序处理。如果这个consumer失效,那么broker会自动切换到其它的consumer。 可以通过Destination Options 来创建一个Exclusive Consumer,

2.6.2 Message Groups

用Apache官方文档的话说,Message Groups rock!它是Exclusive Consumer功能的增强。逻辑上,Message Groups 可以看成是一种并发的Exclusive Consumer。跟所有的消息都由唯一的consumer处理不同,JMS 消息属性JMSXGroupID 被用来区分message group。Message Groups特性保证所有具有相同JMSXGroupID 的消息会被分发到相同的consumer(只要这个consumer保持active)。

另外一方面,Message Groups特性也是一种负载均衡的机制。 在一个消息被分发到consumer之前,broker首先检查消息JMSXGroupID属性。如果存在,那么broker 会检查是否有某个consumer拥有这个message group。如果没有,那么broker会选择一个consumer,并将它关联到这个message group。此后,这个consumer会接收这个message group的所有消息,直到:
• Consumer被关闭。
• Message group被关闭。

2.6.3 消息过滤 JMS Selectors

JMS Selectors用于在订阅中,基于消息属性对消息进行过滤。JMS Selectors由SQL92语法定义。以下是个Selectors的例子:
Java代码
consumer = session.createConsumer(destination, "JMSType = 'car' AND weight> 2500");
在JMS Selectors表达式中,可以使用IN、NOT IN、LIKE等,例如: LIKE '12%3' ('123' true,'12993' true,'1234' false) LIKE 'l_se' ('lose' true,'loose' false) LIKE '\_%' ESCAPE '\' ('_foo' true,'foo' false) 需要注意的是,JMS Selectors表达式中的日期和时间需要使用标准的long型毫秒值。

2.6.4 消息拉取限制策略 Pending Message Limit Strategy

首先简要介绍一下prefetch机制。

ActiveMQ通过prefetch机制来提高性能,这意味这客户端的内存里可能会缓存一定数量的消息。缓存消息的数量由prefetch limit来控制。当某个consumer的prefetch buffer已经达到上限,那么broker不会再向consumer分发消息,直到consumer向broker发送消息的确认。

可以通过在ActiveMQConnectionFactory或者ActiveMQConnection上设置ActiveMQPrefetchPolicy对象来配置prefetch policy。也可以通过connection options或者destination options来配置。例如:
tcp://localhost:61616?jms.prefetchPolicy.all=50

tcp://localhost:61616?jms.prefetchPolicy.queuePrefetch=1

queue = newActiveMQQueue("TEST.QUEUE?consumer.prefetchSize=10"); prefetch size的缺省值如下:
• persistent queues (default value: 1000)
• non-persistent queues (default value: 1000)
• persistent topics (default value: 100)
• non-persistent topics (default value: Short.MAX_VALUE -1)
慢消费者会在非持久的topics上导致问题:一旦消息积压起来,会导致broker把大量消息保存在内存中,broker也会因此而变慢。

未来ActiveMQ可能会实现磁盘缓存,但是这也还是会存在性能问题。目前ActiveMQ使用Pending Message Limit Strategy来解决这个问题。除了prefetch buffer之外,你还要配置缓存消息的上限,超过这个上限后,新消息到来时会丢弃旧消息。通过在配置文件的destination map中配置PendingMessageLimitStrategy,可以为不用的topic namespace配置不同的策略。目前有以下两种:
• ConstantPendingMessageLimitStrategy。这个策略使用常量限制。 例如:<constantPendingMessageLimitStrategylimit="50"/>
• PrefetchRatePendingMessageLimitStrategy。这个策略使用prefetch size的倍数限制。 例如:<prefetchRatePendingMessageLimitStrategymultiplier="2.5"/>
在以上两种方式中,如果设置0意味着除了prefetch之外不再缓存消息;如果设置-1意味着禁止丢弃消息。 此外,你还可以配置消息的丢弃策略,目前有以下两种:
• oldestMessageEvictionStrategy。这个策略丢弃最旧的消息。
• oldestMessageWithLowestPriorityEvictionStrategy。这个策略丢弃最旧的,而且具有最低优先级的消息。

2.6.5 Composite Destinations

从1.1版本起, ActiveMQ支持composite destinations。它允许用一个虚拟的destination 代表多个destinations。例如你可以通过composite destinations在一个操作中同时向12个queue发送消息。在composite destinations中,多个destination之间采用","分割。例如:
Java代码
1. Queue queue = new ActiveMQQueue("FOO.A,FOO.B,FOO.C");
如果你希望使用不同类型的destination,那么需要加上前缀如queue:// 或topic://,例如:
Java代码
1. Queue queue = new ActiveMQQueue("FOO.A,topic://NOTIFY.FOO.A");

2.6.6 Mirrored Queues

每个queue中的消息只能被一个consumer消费。然而,有时候你可能希望能够监视生产者和消费者之间的消息流。你可以通过使用Virtual Destinations 来建立一个virtual queue 来把消息转发到多个queues中。但是 为系统中每个queue都进行如此的配置可能会很麻烦。 ActiveMQ支持Mirrored Queues。Broker会把发送到某个queue的所有消息转发到一个名称类似的topic,因此监控程序可以订阅这个mirrored queue topic。为了启用Mirrored Queues,首先要将BrokerService的useMirroredQueues属性设置成true,然后可以通过destinationInterceptors设置其它属性,如mirror topic的前缀,缺省是"VirtualTopic.Mirror."。

2.6.7 Wildcards

Wildcards用来支持联合的名字分层体系(federated name hierarchies)。它不是JMS规范的一部分,而是ActiveMQ的扩展。ActiveMQ支持以下三种wildcards:
• "." 用于作为路径上名字间的分隔符。
• "*" 用于匹配路径上的任何名字。
• ">" 用于递归地匹配任何以这个名字开始的destination。

2.6.8 Async Sends

ActiveMQ支持以同步(sync)方式或者异步(async)方式向broker发送消息。 使用何种方式对send方法的延迟有巨大的影响。对于生产者来说,既然延迟是决定吞吐量的重要因素,那么使用异步发送方式会极大地提高系统的性能。 ActiveMQ缺省使用异步传输方式。但是按照JMS规范,当在事务外发送持久化消息的时候,ActiveMQ会强制使用同步发送方式。在这种情况下,每一次发送都是同步的,而且阻塞到收到broker的应答。这个应答保证了broker已经成功地将消息持久化,而且不会丢失。但是这样作也严重地影响了性能。 如果你的系统可以容忍少量的消息丢失,那么可以在事务外发送持久消息的时候,选择使用异步方式。以下是几种不同的配置方式:

2.6.9 调度策略 Dispatch Policies

2.6.9.1 Round Robin Dispatch Policy

在2.6.4小节介绍过ActiveMQ的prefetch机制,ActiveMQ的缺省参数是针对处理大量消息时的高性能和高吞吐量而设置的。

所以缺省的prefetch参数比较大,而且缺省的dispatch policies会尝试尽可能快的填满prefetch缓冲。然而在有些情况下,例如只有少量的消息而且单个消息的处理时间比较长,那么在缺省的prefetch和dispatch policies下,这些少量的消息总是倾向于被分发到个别的consumer上。这样就会因为负载的不均衡分配而导致处理时间的增加。

Round robin dispatch policy会尝试平均分发消息,以下是ActiveMQ配置文件的一个例子:
Xml代码
1. <destinationPolicy>
2. <policyMap>
3. <policyEntries>
4. <policyEntry topic="FOO.>">
5. <dispatchPolicy>
6. <roundRobinDispatchPolicy />
7. </dispatchPolicy>
8. </policyEntry>
9. </policyEntries>
10. </policyMap>
11.</destinationPolicy>

2.6.9.2 Strict Order Dispatch Policy

有时候需要保证不同的topic consumer以相同的顺序接收消息。通常ActiveMQ会保证topic consumer以相同的顺序接收来自同一个producer的消息。然而,由于多线程和异步处理,不同的topic consumer可能会以不同的顺序接收来自不同producer的消息。例如有两个producer,分别是P和Q。差不多是同一时间内,P发送了P1、P2和P3三个消息;Q发送了Q1和Q2两个消息。两个不同的consumer可能会以以下顺序接收到消息:
consumer1: P1 P2 Q1 P3 Q2

consumer2: P1 Q1 Q2 P2 P3

Strict order dispatch policy 会保证每个topic consumer会以相同的顺序接收消息,代价是性能上的损失。以下是采用了strict order dispatch policy后,两个不同的consumer可能以以下的顺序接收消息:

consumer1: P1 P2 Q1 P3 Q2

consumer2: P1 P2 Q1 P3 Q2

即,不同的consumer收到的消息顺序是一致的。

2.6.10 消息游标 Message Cursors

当producer发送的持久化消息到达broker之后,broker首先会把它保存在持久存储中。接下来,如果发现当前有活跃的consumer,而且这个consumer消费消息的速度能跟上producer生产消息的速度,那么ActiveMQ会直接把消息传递给broker内部跟这个consumer关联的dispatch queue;如果当前没有活跃的consumer或者consumer消费消息的速度跟不上producer生产消息的速度,那么ActiveMQ会使用Pending Message Cursors保存对消息的引用。在需要的时候,Pending Message Cursors把消息引用传递给broker内部跟这个consumer关联的dispatch queue。以下是两种Pending Message Cursors:
• VM Cursor。在内存中保存消息的引用。
• File Cursor。首先在内存中保存消息的引用,如果内存使用量达到上限,那么会把消息引用保存到临时文件中。
在缺省情况下,ActiveMQ 5.0根据使用的Message Store来决定使用何种类型的Message Cursors,但是你可以根据destination来配置Message Cursors。
对于topic,可以使用的pendingSubscriberPolicy 有vmCursor和fileCursor。可以使用的PendingDurableSubscriberMessageStoragePolicy有vmDurableCursor 和 fileDurableSubscriberCursor。

2.6.11 可优化的确认机制 Optimized Acknowledgement

ActiveMQ缺省支持批量确认消息。由于批量确认会提高性能,因此这是缺省的确认方式。如果希望在应用程序中禁止经过优化的确认方式,那么可以采用如下方法:
Java代码
1. cf = new ActiveMQConnectionFactory("tcp://locahost:61616?jms.optimizeAcknowledge=false");
2.((ActiveMQConnectionFactory)connectionFactory).setOptimizeAcknowledge(false);
3. ((ActiveMQConnection)connection).setOptimizeAcknowledge(false);

2.6.12 Producer Flow Control

同步发送消息的producer会自动使用producer flow control ;对于异步发送消息的producer,要使用producer flow control,你先要为connection配置一个ProducerWindowSize参数,如下:
Java代码
1. ((ActiveMQConnectionFactory)cf).setProducerWindowSize(1024000);
ProducerWindowSize是producer在发送消息的过程中,收到broker对于之前发送消息的确认之前, 能够发送消息的最大字节数。你也可以禁用producer flow control,以下是ActiveMQ配置文件的一个例子:

2.6.13 Message Transformation

有时候需要在JMSProvider内部进行message的转换。

三、ActiveMQ可视化界面

启动完毕后,在浏览器地址栏输入http://localhost:8161/admin,打开ActiveMQ的管理界面。默认用户名密码为admin、admin,这个用户名密码是在conf/users.properties中配置的。输入用户名密码后即可访问到如下管理界面,

ActiveMQ中,61616为消息代理的端口,采用TCP协议发送;8161为管理界面的端口,采用内嵌jetty服务器。

界面如图: 

1.Queues类型界面

Queues选项卡字段


Name:Queues的名字
Number Of Pending Message:等待处理的消息(已接收+已持久化+还在投递队列中)
Number Of Consumers:消费者的数量


Messages Enqueued:进入队列的消息的总数
Messages Dequeued:出队列的消息的总数(被消费)


Views — Browse:查看每一条消息明细
Views — Active Consumers:活动的消费者
Views — Active Producers:活动的生产者
Operations — Send To:手工发送消息
Operations — Purge: 清除队列中的消息
Operations — Delete:删除这个队


原文链接:

ActiveMQ安装及部署教程图解

https://blog.csdn.net/csj50/article/details/86556835

2.Topics类型界面

Topics选项卡字段


Name:Topics的名字
Number Of Consumers:消费者的数量
Messages Enqueued:发布的消息的总数
Messages Dequeued:被订阅的消息的总数(被消费)
Operations:可选操作

 1.Active Subscribers

 Client ID & Connection ID:客户端ID和连接ID
SessionId:客户端连接MQ的会话ID
SubscriptionId:订阅ID
Selector:消息过滤的条数
Active:客户端是否可用
Network:是否集群连接
Pending Queue Size:等待处理的队列大小(积压的数量)
Inflight:inflight messages(空中消息数量,发送了但未确认的消息)
Enqueued:进入队列的消息条数
Dequeued:出队列的消息条数
Prefetch:一次最大推送条数
Subscription Name:订阅者的名字
 

参考资料

1.activemq的官方中文文档
https://www.cnblogs.com/duan2/p/9006607.html

2.

https://blog.csdn.net/csj50/article/details/86556835

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值