你家小区下面有没有快递柜

近两年来,我们收取快递的方式好像变了,变得我们其实并不需要见到快递小哥也能拿到自己的快递了。对,我说的就是类似快递柜、菜鸟驿站这类的代收点的出现,把我们原来快递小哥必须拿着快递让你签收的形式,变为了你下班后去指定地方输入验证码取出你的快递就行了,再也不用麻烦保安大哥或者寄到公司后再带回家去,这个改变你不感觉大大方便了我们这些剁手党么?并且如果你买的是什么见不得人的东西,如什么情趣、什么娃娃的也并不那么尴尬了。

更神奇的是,去年有段时间我们公司的早餐都是有早餐柜子的,你提前订好一周的或者明天的,当你到公司门口,你的早餐已经在保温柜里了,你自己去取出来就行了。并不需要我们拿着钱,然后跟买早餐的阿姨说,两个包子不要肉的。

什么是消息队列

我认为上面的事情就是现实中的消息队列,或者说类似与我们软件中的消息队列,并且它们都是异步的。

在计算机科学中,消息队列(Message queue)是一种进程间通信或同一进程的不同线程间的通信方式,软件的贮列用来处理一系列的输入,通常是来自用户。消息队列提供了异步的通信协议,每一个贮列中的纪录包含详细说明的数据,包含发生的时间,输入设备的种类,以及特定的输入参数,也就是说:消息的发送者和接收者不需要同时与消息队列互交。消息会保存在队列中,直到接收者取回它。
来自维基百科

我来说一下上面的「快递柜」的例子,其实快递柜我们就可以理解为消息容器,快递就是我们系统中的消息,生产者肯定就是快递公司或者卖家了,那我们想都不用想本来就是消费者。
正常来说,快递公司是要负责任的亲自把货物送到我们手中,当然之前他们也是这么做的,这种传统的方式我们可以理解为我们的 HTTP 请求,就是我们一直使用的同步方式,双方必须同时有反馈产生,我们才认为完成了改操作,就是快递小哥让你签收了快递才送这单儿正式完成了。在快递投递的传统方式下就产生了一系列用户体验方面的问题,比如,快递地址是家里,这时候你在公司上班,并且你并不急需这个快递。这种情况下,快递柜子就解决了这个问题,一是并不打扰你日常工作(我试过一天接到三个快递电话),还能提高快递投递效率,何乐而不为呢!这种方式就是程序中的异步的,它允许接收者在消息发送很长时间后再取回消息,提高服务器处理性能,而且还能一定程度降低耦合,这其实就是消息队列。

JMS 代表着什么

JMS(Java Messaging Service)Java 消息服务是 Java 平台上有关面向消息中间件(MOM)的技术规范,它便于消息系统中的 Java 应用程序进行消息交换,并且通过提供标准的产生、发送、接收消息的接口简化企业应用的开发。

也就是说它定义看一系列规范,然后大家按照这种规范来开发自己消息服务,当然,现在有好多开源的来供大家使用了,比较常用的有 Apache ActiveMQ、RabbitMQ、Redis、Jafka/Kafka 等等这些。

Java 消息服务应用程序结构支持两种模型:点对点或队列模型、发布者/订阅者模型。

点对点或队列模型意思一个生产者向一个特定的队列发布消息,一个消费者从该队列中读取消息。有且只有一个消费者将获得消息,生产者不需要在接收者消费该消息期间处于运行状态,接收者也同样不需要在消息发送时处于运行状态。
发布者/订阅者模型则是向一个特定的消息主题发布消息。0 或 n 个订阅者可能对接收来自特定消息主题的消息感兴趣。在这种模型下,发布者和订阅者彼此不知道对方。多个消费者可以获得消息,在发布者和订阅者之间存在时间依赖性。发布者需要建立一个订阅(subscription),以便客户能够订阅。订阅者必须保持持续的活动状态以接收消息,除非订阅者建立了持久的订阅。

说说我的选择

通过标题其实你已经知道了,我选择了 Apache ActiveMQ 来做消息队列的实现,并且我们的项目中貌似还不需要发布者/订阅者这种消息模型,所以,我这里也是采用点对点模型用于示例演示。当然,这里你们也不要问我为啥不选用 Redis ,我不想解释。

这篇文章也是没有所谓的「干货」,下一篇 从零开始学 Java - Spring 集成 ActiveMQ 配置(二) 会有的,但我还是想说,这个思考过程很重要。下一篇会讲到 ActivMQ 与 Spring 框架的整合配置,以及我们的多队列配置、断线重连机制,当然还有的生产者及消费监听者的具体代码实现,这些都会有(不重要)。

如果你有兴趣可以去我的 GitHub 上关于 Spring 的示例项目看看:https://github.com/mafly/SpringDemo