activemq中的消费者生成及消息处理

来源:互联网 发布:php socket编程 断开 编辑:程序博客网 时间:2024/06/06 19:04


增加一个消息消费者


transportConnection中注册了一个消息监听器DefaultTransportListener当客户端有动作的的时候,通过消息监听器的oncommand进行处理。


当有一个消费者进入,则调用该类中的processAddConsumer方法。具体调用流程如下:




消息到达服务器端之后,会被Subscriptionadd方法处理。主要内容是判断消息所属的destination是否存在,如果不存在,则直接返回。存在则将消息添加到PendingMessageCursor中。PendingMessageCursor是用于处理给消费者发送的消息的游标。也就相当于缓存要发给消费者的消息。


Subscription接口:通过接口定义的行为,我们可以看出,主要是和消息的发布的行为相关。比如ad(messageReference)是增加一个消息,add(ConnectionContext context, Destination destination)则是增加一个一个订阅的消息终端。


每一个订阅对应一个客户端,在每一个订阅对象中,存在一个主题list。那么该订阅就能记录所有的该用户订阅的主题。当增加一个订阅的时候,执行如下方法: 


destinations.add(destination);//AbstractSubscription


pending.add(context,destination);//PrefetchSubscription


对应的实现类PrefetchSubscription中存在一个PendingMessageCursor属性,他是一个将消息发送给客户端的游标。



 


那么,一个游标怎么能够处理所有的订阅主题呢??


我们以topic处理对应的游标StoreDurableSubscriberCursor来分析。我们来看游标中这两个属性:



所以,当添加一个消费者订阅的时候,在执行pending.add(context,destination);//PrefetchSubscription这个方法的时候,也就是执行了StoreDurableSubscriberCursor中的add方法:

 


 @Override


   publicsynchronizedvoidadd(ConnectionContext context, Destination destination)throws Exception {


       if (destination !=null && !AdvisorySupport.isAdvisoryTopic(destination.getActiveMQDestination())){


           TopicStorePrefetchtsp= new TopicStorePrefetch(this.subscription,(Topic)destination,clientId,subscriberName);


           tsp.setMaxBatchSize(destination.getMaxPageSize());


           tsp.setSystemUsage(systemUsage);


           tsp.setMessageAudit(getMessageAudit());


           tsp.setEnableAudit(isEnableAudit());


           tsp.setMemoryUsageHighWaterMark(getMemoryUsageHighWaterMark());


           tsp.setUseCache(isUseCache());


           tsp.setCacheEnabled(isUseCache()&& tsp.isEmpty());


           topics.put(destination, tsp);


           storePrefetches.add(tsp);


           if (isStarted()) {


               tsp.start();


           }


       }


   }


在该方法中构建一个TopicStorePrefetch对象,并添加到订阅的list中。所以,cursor就有了通过一个游标管理所有主题消息分发的能力。


上面只是添加一个消费者的流程,他和订阅以及生产者都不是一条线。


同构建一个消费者一样,构建一个生产者也是这个流程。


发送消息


org.apache.activemq.broker.region.policy.SimpleDispatchPolicy


发送消息的处理流程基本如下:



前面的两步相对比较简单,看topicsend方法。


topic持有一个list属性用来存储该topic下的所有的订阅


所以呢在发消息的时候,直接向改topic下所有的订阅者发送就可以啦



向一个订阅发送消息


向一个订阅发送消息,也就是通过Subscription中的add(MessageReference node)方法进行发送。


其实这个方法核心代码也就两行:


pending.addMessageLast(node);


dispatchPending();


先看pending中的addMessagelast



这个方法中,如果消息是不需要持久化的,则直接添加到了nonPersistent中。如果需要持久化,则添加到了TopicStorePrefetch中。


注意,这里的nonPersistent是根据brokerService中的persistent配置来生成的,如果该属性为true,则生成一个FilePendingMessageCursor,否则生成一个VMPendingMessageCursor。他们都是临时存储消息的。只不过一个是通过文件存储,一个是通过jvm存储的。



0 0
原创粉丝点击