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;
                }
            }
        };

配置参数:
ActiveMQ高级应用_第1张图片
使用 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=50value>
        property>
bean> 


<bean id="activeMQConnectionFactory2" class="org.apache.activemq.ActiveMQConnectionFactory" >
        <property name="brokerURL">
            <value>tcp://localhost:61616?jms.prefetchPolicy.queuePrefetch=1value>
        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,流程图如下:
ActiveMQ高级应用_第2张图片

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

VM游标

消息接收后,首先完成消息存储的工作,然后直接把消息存放在pendingCursor,发送给目标队列
ActiveMQ高级应用_第4张图片
注意:vm方式建议在内存足够大的情况下使用,而且vm方式不适合处理慢消费,vmCursor+非持久时,直接变成一个内存MQ,为了防止内存溢出,在消息积压到指定数量的时候,PFC会阻止生产消息。

File游标

包含vm的处理方式,如果broker内存已经耗尽,则会将消息先存在临时文件中,当需要将消息发送到dispatch中去时,则使用pending cursor去读取一批临时文件中的数据
ActiveMQ高级应用_第5张图片
注意这里当内存不够用时,实际上会操作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配置文件功能,需要做如下配置即可:

"http://activemq.apache.org/schema/core" start="false" ... >    
    
      "1000" />
    
    ...
 

plugins:支持添加插件
runtimeConfigurationPlugin:允许动态修改配置文件的插件,checkPeriod表示割多少时间去检查一次
注意:
start=”false” 这个属性表示spring不会自动的将broker启动,会首先保证插件初始化。

支持动态修改的属性有




你可能感兴趣的:(activemq)