• ActiveMQ in Action(7)


    关键字: activemq

    2.6.7 Wildcards
        Wildcards用来支持联合的名字分层体系(federated name hierarchies)。它不是JMS规范的一部分,而是ActiveMQ的扩展。ActiveMQ支持以下三种wildcards:

    • "." 用于作为路径上名字间的分隔符。
    • "*" 用于匹配路径上的任何名字。
    • ">" 用于递归地匹配任何以这个名字开始的destination。

       作为一种组织事件和订阅感兴趣那部分信息的一种方法,这个概念在金融市场领域已经流行了一段时间了。设想你有以下两个destination:

    • PRICE.STOCK.NASDAQ.IBM (IBM在NASDAQ的股价)
    • PRICE.STOCK.NYSE.SUNW (SUN在纽约证券交易所的股价)

       订阅者可以明确地指定destination的名字来订阅消息,或者它也可以使用wildcards来定义一个分层的模式来匹配它希望订阅的destination。例如:

    Subscription Meaning
    PRICE.> Any price for any product on any exchange
    PRICE.STOCK.> Any price for a stock on any exchange
    PRICE.STOCK.NASDAQ.* Any stock price on NASDAQ
    PRICE.STOCK.*.IBM Any IBM stock price on any exchange

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

    Java代码  收藏代码
    1. cf = new ActiveMQConnectionFactory("tcp://locahost:61616?jms.useAsyncSend=true");  
    2. ((ActiveMQConnectionFactory)connectionFactory).setUseAsyncSend(true);  
    3. ((ActiveMQConnection)connection).setUseAsyncSend(true);  

    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

       以下是ActiveMQ配置文件的一个例子:

    Xml代码  收藏代码
    1. <destinationPolicy>  
    2.   <policyMap>  
    3.     <policyEntries>  
    4.       <policyEntry topic=""FOO.>">  
    5.         <dispatchPolicy>  
    6.           <strictOrderDispatchPolicy />  
    7.         </dispatchPolicy>  
    8.       </policyEntry>  
    9.     </policyEntries>  
    10.   </policyMap>  
    11. </destinationPolicy>  

    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。以下是ActiveMQ配置文件的一个例子:
    Xml代码  收藏代码
    1. <destinationPolicy>  
    2.   <policyMap>  
    3.     <policyEntries>  
    4.       <policyEntry topic="org.apache.>">  
    5.         <pendingSubscriberPolicy>  
    6.           <vmCursor />  
    7.         </pendingSubscriberPolicy>  
    8.         <PendingDurableSubscriberMessageStoragePolicy>  
    9.           <vmDurableCursor/>  
    10.         </PendingDurableSubscriberMessageStoragePolicy>  
    11.       </policyEntry>  
    12.     </policyEntries>  
    13.   </policyMap>  
    14. </destinationPolicy>  

       对于queue,可以使用的pendingQueuePolicy有vmQueueCursor 和 fileQueueCursor。以下是ActiveMQ配置文件的一个例子:

    Xml代码  收藏代码
    1. <destinationPolicy>  
    2.   <policyMap>  
    3.     <policyEntries>  
    4.       <policyEntry queue="org.apache.>">  
    5.         <pendingQueuePolicy>  
    6.           <vmQueueCursor />  
    7.         </pendingQueuePolicy>  
    8.       </policyEntry>  
    9.     </policyEntries>  
    10.   </policyMap>  
    11. </destinationPolicy>  

    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配置文件的一个例子:
    Java代码  收藏代码
    1. <destinationPolicy>  
    2.   <policyMap>  
    3.     <policyEntries>  
    4.       <policyEntry topic="FOO.>" producerFlowControl="false">  
    5.         <dispatchPolicy>  
    6.           <strictOrderDispatchPolicy/>  
    7.         </dispatchPolicy>  
    8.       </policyEntry>  
    9.     </policyEntries>  
    10.   </policyMap>  
    11. </destinationPolicy>  

    2.6.13 Message Transformation
        有时候需要在JMS provider内部进行message的转换。从4.2版本起,ActiveMQ 提供了一个MessageTransformer 接口用于进行消息转换,如下:

    Java代码  收藏代码
    1. public interface MessageTransformer {  
    2.     Message producerTransform(Session session, MessageProducer producer, Message message) throws JMSException;  
    3.     Message consumerTransform(Session session, MessageConsumer consumer, Message message)throws JMSException;  
    4. }  
        通过在以下对象上通过调用setTransformer方法来设置MessageTransformer:
    • ActiveMQConnectionFactory
    • ActiveMQConnection
    • ActiveMQSession
    • ActiveMQMessageConsumer
    • ActiveMQMessageProducer

       MessageTransformer接口支持:

    • 在消息被发送到JMS provider的消息总线前进行转换。通过producerTransform方法。
    • 在消息到达消息总线后,但是在consumer接收到消息前进行转换。通过consumerTransform方法。

       以下是个简单的例子:  

    Java代码  收藏代码
    1. public class SimpleMessage implements Serializable {  
    2.     //  
    3.     private static final long serialVersionUID = 2251041841871975105L;  
    4.       
    5.     //  
    6.     private String id;  
    7.     private String text;  
    8.       
    9.     public String getId() {  
    10.         return id;  
    11.     }  
    12.     public void setId(String id) {  
    13.         this.id = id;  
    14.     }  
    15.     public String getText() {  
    16.         return text;  
    17.     }  
    18.     public void setText(String text) {  
    19.         this.text = text;  
    20.     }  
    21. }  
        在producer内发送ObjectMessage,如下:
    Java代码  收藏代码
    1. SimpleMessage sm = new SimpleMessage();  
    2. sm.setId("1");  
    3. sm.setText("this is a sample message");  
    4. ObjectMessage message = session.createObjectMessage();  
    5. message.setObject(sm);  
    6. producer.send(message);  

       在consumer的session上设置一个MessageTransformer用于将ObjectMessage转换成TextMessage,如下:

    Java代码 复制代码
    1. ((ActiveMQSession)session).setTransformer(new MessageTransformer() {   
    2. public Message consumerTransform(Session session, MessageConsumer consumer, Message message) throws JMSException {   
    3.     ObjectMessage om = (ObjectMessage)message;   
    4.     XStream xstream = new XStream();   
    5.     xstream.alias("simple message", SimpleMessage.class);   
    6.     String xml = xstream.toXML(om.getObject());   
    7.     return session.createTextMessage(xml);   
    8. }   
    9.   
    10. public Message producerTransform(Session session, MessageProducer consumer, Message message) throws JMSException {   
    11.     return null;   
    12. }   
    13. });  
  • 相关阅读:
    DWR组件——基于远程过程调用实现Ajax
    JSTL学习笔记
    EL表达式学习笔记
    JavaScript学习笔记
    原生Ajax使用教程
    Response的返回内容类型
    Tomcat上文件的绝对路径访问笔记
    JSON语言规范与Java中两种解析工具基本使用
    Java生成XML文件与XML文件的写入
    编码问题笔记
  • 原文地址:https://www.cnblogs.com/ainima/p/6331699.html
Copyright © 2020-2023  润新知