ActiveMQ高级应用

消息延时投递和定时投递(消息延时投递存在消息文件无法删除的BUG,请尽量不要使用。)

场景:有时候我们不希望消息马上被broker投递出去,而是想要消息60秒以后发给消费者,或者我们想让消息没隔一定时间投递一次,一共投递指定的次数

如何使用:

1.首先需要服务器开启定时器支持

<broker xmlns="http://activemq.apache.org/schema/core" brokerName="localhost" schedulerSupport="true"></broker>

2.在发送端代码中设置消息的延时定时属性,部分方法示例如下:

public void send(final Serializable message)    {        MessageCreator creator = new MessageCreator()        {            @Override            public Message createMessage(Session session) throws JMSException            {                if (message instanceof String)                {                    Message msg = session.createTextMessage((String) message);                    //延时60秒钟投递                    msg.setLongProperty(ScheduledMessage.AMQ_SCHEDULED_DELAY,60000);                    //投递10次                    msg.setIntProperty(ScheduledMessage.AMQ_SCHEDULED_REPEAT,10);                    					return msg;                }                else                {                    ObjectMessage objMessage = session.createObjectMessage();                    objMessage.setObject(message);                    return objMessage;                }            }        };

配置参数: 

参数

类型

描述

AMQ_SCHEDULED_DELAY

long

延迟投递的时间

AMQ_SCHEDULED_PERIOD

long

重复投递的时间间隔

AMQ_SCHEDULED_REPEAT

int

重复投递次数

AMQ_SCHEDULED_CRON

String

Cron表达式


使用 CRON 表达式的例子:

// 每小时发生消息投递 message.setStringProperty(ScheduledMessage.AMQ_SCHEDULED_CRON, "0 * * * *");


CRON表达式的优先级高于另外三个参数,如果在设置了CRON的同时,也有repeat和period参数,则会在每次CRON执行的时候,重复投递repeat次,每次间隔为period。就是说设置是叠加的效果。例如每小时都会发生消息被投递10次,延迟1秒开始,每次间隔1秒


复合目的地

场景:如果需要将发往队列 A转发到队列B和主题C,就可以考虑使用复合目的地的方式,配置如下

<destinationInterceptors>      <virtualDestinationInterceptor>        <virtualDestinations>          <compositeQueue name="MY.QUEUE">            <forwardTo>              <queue physicalName="FOO" />              <topic physicalName="BAR" />            </forwardTo>          </compositeQueue>        </virtualDestinations>      </virtualDestinationInterceptor></destinationInterceptors>


Message Group(消息分组)

可以将消息进行分组,JMS 消息属性JMSXGroupID 被用来区分message group,Message Groups特性保证所有具有相同JMSXGroupID 的消息会被分发到相同的consumer(只要这个consumer保持active),可以看作是消息的负载均衡

在一个消息被分发到consumer之前,broker首先检查消息JMSXGroupID属性。如果存在,那么broker 会检查是否有某个consumer拥有这个message group。如果没有,那么broker会选择一个consumer,并将它关联到这个message group。此后,这个consumer会接收这个message group的所有消息,直到当前Consumer被关闭或者是Message group被关闭(通过发送一个消息,并设置这个消息的JMSXGroupSeq为0)

如何使用消息分组,只需要在发送端发送代码中,指定message的JMSXGroupID即可,代码如下:

 msg.setStringProperty("JMXGroupID","aClient");


JMS Selectors

消息选择器,基于消息属性对进行消息的过滤,确保客户端只能消费特定的消息


如何使用JMS Selectors,举例说明

场景:客户端监听A指定消费者去消费某一个message group(JMSXGroupID为aClinet)实现

示例代码如下:

1. 发送端代码参见上一节Message Group消息分组

2. 消费端queue的配置如下

<bean id="hehe" class="org.apache.activemq.command.ActiveMQQueue">  <constructor-arg     value="testQueue_One?consumer.selector=JMXGroupId='aClient'"/></bean> 


prefetch机制

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


有如下几种方式可以使用此机制:

在客户端spring中配置ActiveMQConnectionFactory时配置如下:

<bean id="activeMQConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory" >        <property name="brokerURL">            <value>tcp://localhost:51616?jms.prefetchPolicy.all=50</value><!-- 表示queue或者topic消费者预取数量为50 -->        </property></bean>   <bean id="activeMQConnectionFactory2" class="org.apache.activemq.ActiveMQConnectionFactory" >        <property name="brokerURL">            <value>tcp://localhost:61616?jms.prefetchPolicy.queuePrefetch=1</value><!-- 表示queue消费者预取数量为1 -->        </property></bean>   

或者针对某一个queue或者topic配置如下:

<bean id="hehe" class="org.apache.activemq.command.ActiveMQQueue">    <constructor-arg value="queue?consumer.prefetchSize=10"/></bean> 

prefetch size的缺省值如下:

持久化queue:1000条

非持久化queue: 1000条

持久化topic:100条

非持久化topic: 无限制


消息游标

游标的作用是在于标识下一次将要读取的数据的位置mq支持三种游标

Store-based游标

目前是mq默认使用的游标,可以适用于大部分的场景

快消费时(有可用内存):store-based将直接将消息存储并发送至dispatch,流程图如下:

慢消费(当无可用内存):这时,消息不再直接发往dispatch,而是先存储在文件中,由pending cursor去取文件中的数据,发送给dispatch,流程图如下:

VM游标

消息接收后,首先完成消息存储的工作,然后直接把消息存放在pendingCursor,发送给目标队列

注意:vm方式建议在内存足够大的情况下使用,而且vm方式不适合处理慢消费,vmCursor+非持久时,直接变成一个内存MQ,为了防止内存溢出,在消息积压到指定数量的时候,PFC会阻止生产消息。


File游标

 包含vm的处理方式,如果broker内存已经耗尽,则会将消息先存在临时文件中,当需要将消息发送到dispatch中去时,则使用pending cursor去读取一批临时文件中的数据

注意这里当内存不够用时,实际上会操作2次文件读写,性能相对比较差,适用场景是在,存储比较慢,消费比较快的情况下


如何使用游标

 

需要在服务端配置如下:

topic目的地配置

<destinationPolicy>   <policyMap>     <policyEntries>       <policyEntry topic=">" >           <pendingSubscriberPolicy>                                       <vmCursor></vmCursor> <!—指定为vm游标-- >                              </pendingSubscriberPolicy>       </policyEntry>     </policyEntries>   </policyMap>  </destinationPolicy>


queue目的地配置


<policyEntry queue=">" >    <pendingQueuePolicy>                                <vmQueueCursor></vmQueueCursor> <!—指定为vm游标-- >                         </pendingQueuePolicy></policyEntry>


动态修改配置文件

在5.9.0版本之后,引入了动态修改broker的activemq.xml配置文件功能,需要做如下配置即可:

<broker xmlns="http://activemq.apache.org/schema/core" start="false" ... >        <plugins>      <runtimeConfigurationPlugin checkPeriod="1000" />    </plugins>    ...</broker> 
plugins:支持添加插件
runtimeConfigurationPlugin:允许动态修改配置文件的插件,checkPeriod表示割多少时间去检查一次

注意:

start="false" 这个属性表示spring不会自动的将broker启动,会首先保证插件初始化。


支持动态修改的属性有

 <networkConnectors>

 <destinationPolicy><policyMap><policyEntries>

 <plugins><authorizationPlugin><map><authorizationMap><authorizationEntries>

 <destinationInterceptors><virtualDestinationInterceptor><virtualDestinations>


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值