ActiveMQ从入门到精通(二)

接上一篇《ActiveMQ从入门到精通(一)》,本篇主要讨论的话题是:消息的顺序消费、JMS Selectors、消息的同步/异步接受方式、Message、P2P/PubSub、持久化订阅、持久化消息到MySQL以及与Spring整合等知识。

消息的顺序消费

在上一篇文章中,我们已经明确知道了ActiveMQ并不能保证消费的顺序性,即便我们使用了消息优先级。而在实际开发中,有些场景又是需要对消息进行顺序消费的,比如:用户从下单、到支付、再到发货等。如果使用ActiveMQ该如何保证消费的顺序性呢?

消息消费顺序性

首先来说,在实际中,我们并不需要的是对全部消息的全局有序消费,我们仅仅需要的是局部业务有序性消费。比如说,我们仅仅需要的是一个用户的下订单、支付、发货这个过程的3条消息有序消费。

比如,我们可以根据用户ID简单做一个HASH,将消息定位到不同的队列上,也就意味着同一个用户的消息将发往同一个队列。这样做的好处在于,多个队列之间可以并行处理。

然后,在队列上可以对一段时间上的消息按照用户分组进行排序,这只是一个少量消息的局部排序而已,比如Queue-A上有一个用户的3条消息(订单消息msg1、支付消息msg2、发货消息msg3),那么,msg1将交给订单业务系统,处理完成后,msg2交给支付系统,处理完成后,msg3交给发货系统。虽然这个处理过程是同步的(一条消息处理完,在接着处理),但是它的并发性,系统的处理能力并没有下降!为什么这么说呢?

假设,msg1/msg2/msg3处理各需要0.1S,如果订单业务系统、支付系统、发货系统并没有分开,而是一个“大系统”,那么显然订单业务在0.1S完成后,需要等待后面的支付、发货逻辑处理完才能继续工作,意味着订单业务干了0.1S的活,等了0.2S,导致在0.3秒内订单业务只处理了1条消息。而现在这3个系统是分开的,那么在0.3S内,订单业务系统可以处理3条消息,而且没有业务系统闲着!

实际上,RocketMQ在消费顺序性这块要比ActiveMQ要强大些,后期在RocketMQ专题中再为大家介绍。


JMS Selectors

JMS Selectors,即消息选择器。在《ActiveMQ从入门到精通(一)》中,介绍过消息的组成部分,其中谈到消息对象有消息属性,用于消息选择器。我们来看一个代码片段,你就会明白:

生产者片段


消费者片段

需要注意一下几点:

第一,生产者端需要设置消息属性,一定要注意的是setXxxProperty(filed,value)

第二,给出条件,其实本质上就是SQL92语法

第三,创建消费者的时候,指定条件即可


消息的同步 AND 异步 接受

消息的接受,我们已经知道,可以通过消费者的receive()/receive(long time)/receiveNoWait(),这种方式是client端主动接受消息,可以理解为消息的同步接受。要知道这种同步的消息接受方式,是让我们很难受的,我们不得不写一个死循环来不断接受消息。那么有没有一种比较优雅的方式,比如我们设置一个类似消息监听的机制,一旦队列上有消息了,那么回调我们的message handler进行处理呢?

Message Listener

消息的异步接受是指当消息到达时,ActiveMQ主动通知客户端。可以通过注册一个实现了MessageListener接口的对象到MessageConsumer。MessageListener只有一个必须要实现的方法,即onMessage。在发往Destination的消息时,会调用该方法。

这种异步接受“貌似”是ActiveMQ主动的推送消息给消费者,其本质还是消费者轮询消息服务器导致的,只不过这个过程被封装了!


Message

JMS程序的核心在于,生产和消费的消息能够被其他程序所使用到。JMS Message是一个既简单又不乏灵活的基本格式,由消息头、属性、消息体3部分组成。

Message

注意,在消费者端,我们接受到消息后,一般需要通过instanceof来判断类型后在进行处理!

在ActiveMQ中,还存在一类临时消息,就是通过创建临时队列/临时主题,如果Connection一旦关闭,那么临时目标就关闭,消息内容也就消失。了解下即可,实际中并不适用。


P2P or Pub/Sub

上2张图,你就会明白这2种模式的区别了。

P2P

生产者端发送一条消息,消费者端只会有一个消费者消费这个消息。好像打电话,一对一通信!

Pub/Sub

一对多通信,发送一条消息,所有订阅了该目标的消费者都会收到消息。

P2P、Pub/Sub在代码上的区别点仅仅在于,目标类型的创建是createQueue or createTopic,其他一切照旧!

对于订阅模式,对订阅者提出了特殊的要求,要想收到消息,必须先订阅,而且订阅进程必须一直处于运行状态!实际上,有时候消费者重启了下,那么这个消费者将丢失掉一些消息,那么能否避免这样的情况呢?ActiveMQ已经替我们想好了,就是持久化订阅!


持久化订阅

所谓持久化订阅,打个比方,就是说跟MQ打声招呼,即便我不在,那么给我发送的消息暂存在MQ,等我来了,再给我发过来。说白了,持久化订阅,需要给MQ备个案(你是谁,想在哪个Topic上搞特殊化)!看一个代码片段:

持久化订阅机制

每一个持久化订阅者都应该有一个唯一的ID作为标示以及要在哪个Topic上进行持久化订阅,一旦这些信息告知MQ之后,那么以后不论持久化订阅者在不在线,那么他的消息会暂存在MQ,以后都会发给他!


持久化消息到MySQL

在前文中已经提及默认情况下,ActiveMQ是开启持久化消息机制的,并且是持久化到kahadb的,但是"很可惜"kahadb对我们不是很友好的可视化,其实ActiveMQ提供了配置的方式让我们来选择持久化消息到哪里,这里我以到MySQL为例来说明。(实际上ActiveMQ已经在conf配置文件中提供了相应的例子,我这里就简单说明下)

在activemq.xml的<broker>节点中增加MySQL信息

注意到这个bean的id,这个是要被引用的。

注释kahadb,启用持久化到MySQL配置

实际中,我们会持久化到哪里呢?一般情况下,比如到kahadb,比如到leveldb,因为这些数据库的性能要较MySQL更高些,我们并不关心消息的“可视化”,更加关心的是消息在持久化的同时更加高效!


与Spring整合

这里我将为大家演示Spring和ActiveMQ整合的核心要素。采用Spring,不要Web容器,不涉及Spring-MVC,而且在这里我将采用JUnit + Spring-Test来进行测试!在文章末尾我将提供源码下载。OK,先来看一眼工程截图:

工程结构

第一步:POM.XML配置

maven dependency tree

第二步:MQ信息配置文件、Spring配置文件

activemq.properties


spring-context.xml

下面我们重点关注spring-activemq.xml:

ConnectionFactory

注意从ActiveMQConectionFactory到PooledConnectionFactory,到Spring提供的SingleConnectionFactory,就是一个适配的过程。


生产者、消费者配置

注意Spring的套路经常是这样的,提供XxxTemplate,比如HibernateTemplate,对于JMS,提供了JmsTemplate。

生产者应该持有JmsTemplate进行发送消息。

消费者,提供监听器、监听的目的地、连接工厂即可。

上面的配置,只是一个非常简单的示例,比如是发送到队列,还是发送到主题,事务的配置,签收机制的配置,ttl/priority等配置在后文通过看一下源码,你就会知道该如何配置了。

第三步:消费者实现监听器

spring提供的接口

第四步:生产者

通过注入拿到JmsTemplate

第五步:利用Junit4 + SpringTest方式进行测试

我们以前在测试Spring这一块,大都是通过手动编码的方式(加载XML,setter/getter bean)进行,这里我将为大家介绍一种全新的方式测试Spring程序!

测试基类

为什么要提供一个测试基类呢?因为我们可能有很多个测试类,如果有了这个基类,其他测试类继承它,就可以自动获得测试基类的属性了。

@RunWith  指明采用SpringJunit4进行测试

@ContextConfiguration 告诉配置文件在哪里


生产者测试类

发现没有,这样写Junit单元测试,和以前感觉不一样!

其实,SpringTest + Junit4还提供了很多功能强大的地方,比如可以设置数据库事务。如果我们在测试的过程结束后,希望回滚数据库的话,很简单,只需要在相应方法上打上注解即可。

运行结果

Test Result

JmsTemplate

看一下属性:

JmsTemplate

很多属性,是不是很熟悉呢?

JmsTemplate的父类中有一个重要属性:

pubSubDomain

默认情况下,是P2P模式,如果将这个属性配置成true,那么将是主题模式。


OK,到这里这篇博客的内容就介绍完毕了,下一篇是关于ActiveMQ集群方面的知识,See you again.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容

  • 这是关于消息中间件ActiveMQ的一个系列专题文章,将涵盖JMS、ActiveMQ的初步入门及API详细使用、两...
    张丰哲阅读 94,526评论 52 244
  • JMS是什么 JMS是SUN提出是为了统一MOM系统接口的规范,他包含点对点,以及发布订阅两种消息模型,提供可靠消...
    洁癖汪阅读 379评论 0 0
  • 1.简介 1.1. ActiveMQ 由Apache出品的开源消息总线。是一个完全支持JMS1.1和J2EE ...
    华木公子阅读 2,291评论 0 0
  • 推荐指数: 6.0 书籍主旨关键词:特权、焦点、注意力、语言联想、情景联想 观点: 1.统计学现在叫数据分析,社会...
    Jenaral阅读 5,705评论 0 5
  • 城空了,有树长出来 我的城死了 铸起它的人,杀死它的人 不愿因为这件事而骄傲 一座城的终结 永远因为终结这件事而显...
    于十六阅读 2,852评论 6 17