Java帝国之JMS的诞生

开发 开发工具
其实Java 帝国非常擅长搞出标准的协议和接口, 之前的JDBC就是一个典型的例子(参见文章《JDBC的诞生》), 制定了协议以后, 让各个产品厂商去实现, 实现了针对数据库编程的统一接口。

1.背景

本文续上篇《Java 帝国之消息队列》

自从张家村的ZhangMQ问世以来,大家都看到了消息队列在分布式系统中的巨大好处,纷纷另起炉灶搞一套自己的消息队列,各种MQ产品如雨后春笋班出现,各家都疯狂的宣传自己的宝贝。

为了吸引程序猿来使用, 各家八仙过海,各显神通,定义了各式各样的API, 由于是独立发展,这些API协议多样,互不兼容, 学习成本高,使用起来非常不方便。

这是帝国所不能容忍的 !

其实Java 帝国非常擅长搞出标准的协议和接口, 之前的JDBC就是一个典型的例子(参见文章《JDBC的诞生》), 制定了协议以后, 让各个产品厂商去实现, 实现了针对数据库编程的统一接口。

既然数据库可以这么干, 消息队列肯定也没问题!

由于张家村开发了***个消息队列产品, 帝国把制定标准接口的光荣使命交给了张家村。

2.消息队列接口设计

张家村经验丰富的老村长又把任务分给了小张, 告诉他我们要做的是一个厂商独立的标准接口, 让他先去调研一下时下流行的MQ的现状。

小张先找到了某大厂著名MQ, 它占据了企业级市场不少份额, 但是直接使用它的 Java API 编程的话就不那么容易了, 大家可以快速浏览下:

小张能看的出这是在发送一个消息,但这MQEnvironment, openOptions,MQPutMessageOptions 看起来让小张心烦,特别是还得理解Queue Manager这样的概念,有点不容易。

小张又找了一个以开源吸引人的RabbitMQ , 这个看起来清爽多了:

但是这queueDeclare方法 和 basicPublish 方法小张总觉得的不爽。

只看了两个消息队列, 小张就不想再看了, 他去找村长说: 这差别也太大了,根本无法统一。

村长说:”不要被纷繁的现象迷住了双眼, 要看透背后的本质, 做出适当的抽象才可以。“

又是抽象! 小张暗自叹气, 这抽象实在是太难了。

”你深入思考下“ 村长看出了小张的困难, 鼓励他说: ”其实也没那么难, 我们先搞出几个最基本的概念, 记不记得操作系统中学过的生产者-消费者模型? 我们完全可以应用到这里来啊, 消息生产者(Message Producer), 消息消费者 (Messge Consumer) , 生产者提供发送消息的方法, 消费者提供接收消息的方法, 如果加上消息队列 (Message Queue) 的话就是这样:“

 

小张说:”这也太抽象了吧, 我看人家还有什么Queue Manager, Connection ,Channel 之类的“

村长说: ”别急啊, 你看不管是生产者向队列发送消息,还是消费者去接收消息, 其实都是在和消息队列进行交互, 所以我们再引入一个会话(Session)的概念出来 。“

”奥, 我有点明白了 ,Session 可以创建消息, 还可以引入事务的支持呢“ 小张思维敏捷

“不错, 其实消息生产者/消费者也应该由Session来创建,因为他们要发送/接收消息肯定是在一个会话中, 另外你想想, Session对象由谁来创建?”

小张说: “应该是Connection ” 说着小张画了一张图:

“你看这概念不就出来了,是不是很简单? ” 村长笑着说。

小张挠挠头说: “会者不难,难者不会啊, 对了,我们还缺乏最关键的连接参数(ip地址,端口等)还有队列的名称之类的信息。 这些信息怎么办?”

“这确实有点复杂,各个厂商的具体情况差别太大。” 村长也表示犯难 ,“你让我想想, 下午再聊。”

3.配置和代码的分离

小张中午吃饭的时候也在想, 这些复杂的配置参数该怎么办, 要是都让程序员在代码里写,那就太丑陋了吧, 因为不同的MQ产品,配置都不一样啊。

下午的时候,看到村长一副喜气洋洋的表情, 小张知道问题解决了。

村长说: “我想到了一个办法, 一个很简单,但是有效的办法。”

小张说:“别卖关子了,快说吧”

”其实也是又老又俗的办法了, 这个办法就是把配置和代码分开, 你不是说这些连接参数很复杂,各个厂商不同吗? 那就作为配置信息把它放到Web容器里,对外只提供一个简单的ConnectionFactory的接口,由这个ConnectionFactory来创建Connection, 当然了各个厂商必须实现这个ConnectionFactory“

"那怎么才能得到这个ConnectionFactory ?"

"这就简单了, 对程序员来讲,通过JNDI 就可以轻松拿到了, 例如:"

”这办法不错,把细节都隐藏起来了, 既然ConnectionFactory可以这么搞, 队列(Queue)的配置信息也可以这么办啊。“

村长说:”所以ConnectionFactory, Queue 就是隔离细节的抽象层。”

4.再次抽象

标准接口初具模型,小张很高兴,晚上请喜欢的张二妮吃饭, 忍不住得瑟了一下。

张二妮说:“你们两个老土,定义的标准接口,都已经过时了!”

小张很生气: “怎么可能呢?”

二妮说:“告诉你们吧, 你们搞的这个叫Point to Point模型,就是一个发送方,对应一个接收方, 现在外边有很多人在用 发布/订阅 的模型,你们知道不? ”

“一个客户端(Client1)对一个Topic发布了消息, 很多订阅了这个Topic的客户端(Client2, Client3) 都可以接收到这个消息的副本。”

小张呆住了, 这和以前ZhangMQ的方式完全不同, 队列都不见了, 引入了一个新的主题(Topic)的概念。

第二天, 小张赶紧去找村长, 告诉他发生了新情况。

村长说: “你呀,还是太年轻, 慌什么,深入思考一下, 这个发布/订阅的本质和我们之前的生产者/消费者没什么不同。 ”

小张说: “那人家还有Topic的概念呢。”

“我们可以把Topic和Queue 变成一个更抽象的概念,他们都是消息的目的地, 嗯, 就叫做Destination吧,这个Destination的细节也是需要配置出来的, 通过JNDI来获取。”

“那订阅怎么处理?”

村长说: “原来我们定义的是MessageConsumer, 现在增加一个新概念叫做 TopicSubscriber , 可以从Destination获取消息,这不就行了, 其实从本质上来讲Subscriber也是消息消费者的一种而已。”

“那怎么才能实现订阅的功能呢?”

“别忘了, 我们只定义接口行为, 具体的实现需要由各个产品来负责!”

小张看着这幅图, 深感抽象的威力巨大, 这么多的细节***变成了这几个简单的概念!

小张还特意写了一段代码,展示上面的概念:

张家村把这个设计交了上去, 帝国很满意,把它起名为Java Message Service (JMS), 随后强制各大产品实现JMS, 否则就不颁发进京证, 没这个证别想在帝国做生意!

JMS由于设计良好,概念清晰,其实不用怎么强制,很快就流行开了,成为了Java 帝国的事实标准。

【本文为51CTO专栏作者“刘欣”的原创稿件,转载请通过作者微信公众号coderising获取授权】

戳这里,看该作者更多好文

责任编辑:武晓燕 来源: 51CTO专栏
相关推荐

2018-09-13 14:18:20

C语言Java程序员

2017-10-12 14:56:11

2017-02-27 14:25:50

Java队列Web

2017-08-16 15:11:29

JavaJDBCJTA

2018-03-29 15:20:05

JavaJaasJdbc

2015-08-11 14:09:44

2017-11-22 14:31:24

华为云

2017-11-14 14:41:11

Java泛型IO

2009-04-27 12:42:54

技术周刊收购Oracle

2010-10-12 11:02:42

职场

2009-06-25 15:33:13

Java消息服务JMS

2009-04-20 23:29:12

Oracle收购Sun甲骨文

2013-10-22 10:23:12

2019-02-26 11:21:19

PythonJava渗透

2019-04-29 09:42:06

Java函数Python

2017-08-03 15:44:22

2017-08-22 16:25:14

CSSHTML选择器

2010-09-20 11:39:50

2009-06-17 16:56:46

Spring JMS

2021-02-03 11:44:15

NoSQL关系数据库
点赞
收藏

51CTO技术栈公众号