zl程序教程

您现在的位置是:首页 >  其他

当前栏目

看完这篇,还怕面试官问消息中间件么?

2023-03-07 09:13:44 时间

注:文内内容为依据本人理解创作,如果错误,请留言告知。

先说需求

如果现有A、B两个应用程序,B应用希望从A应用获取到自己感兴趣的信息,A和B部署在不同的机房,可能还有C、D、E等更多的这样的应用程序需要A的这些消息,这就是我们常说的消息中间件的点对点、发布订阅模式。

说到消息中间件,工作中经常会用到MQ消息中间件,常见的消息中间件有Apache的ActiveMQ以及RabbitMQ。

不管是ActiveMQ还是RabbitMQ都是基于JMS规范的消息中间件,它们都是消息服务的“提供者”。

那么什么是 JMS?Java Message Service (JMS)是Java中面向消息中间件为两个或者多个组件之间发送消息的客户端,它是生产者和消费者问题的一种实现。JMS是Java平台企业版的一部分,目的是为了允许组件之间的通讯被松耦合、可靠、并且异步。

JMS 的 API 编程模型

1.弄清楚基本元素

首先要搞清楚消息服务中的几个元素,即 提供者,客户端、生产者/发布者,使用者/订阅者,JMS消息,JMS队列、JMS主题。

JMS 提供者(provider),这个很好理解,可以理解为消息的容器、消息的载体、消息的家,比如ActiveMQ就是一个 JMS 提供者,它为JMS提供了中间的服务。

JMS 客户端(Client),指的是一个产生或者消费消息的一个进程或者应用。

JMS 生产者/发布者(producer/publisher)使用者/订阅者(consumer/subscriber)是对应的关系表示的是创建发送和接收消息的客户端。

JMS 消息(Message),即一个对象,表示 JMS 传输的数据,可以是一段文字,一个序列化的Java对象等等。

JMS 队列(Queue),这个概念比较重要,JMS中的队列是一个暂存区域,存储的是 JMS 中已经发送成功但是等待读取的消息(点对点模式下)。顾名思义,消息按照发送顺序传递,JMS队列保证每条消息都仅被处理一次。

JMS 主题(Topic),指的是一个发布机制,也就是我们常说的发布订阅模式。

为了方便理解,我找到了这两张图片

点对点JMS消息传递

发布订阅JMS消息传递

2.想明白两种发布模式

JMS支持两种不同的消息发布模式,通过下面的解释,应该很容易明白。

No.1 点对点

在点对点消息传递模式下,消息被生产者传递到消息队列中。这种消息类型基于消息队列的发送方和接收方,每条消息都被发送到一个特定的队列中,消费者也就是接收客户端从保存了消息的队列中提取消息,队列的好处就是保证每条消息都会被消费,并且只会被一个消费者消费一次。消息队列会保留发送者也就是消息制造者的所有消息,直到消息被消费或者过期。

No.2 发布订阅

说完了点对点,接下来就是发布订阅,通过上面的图片能清晰的看到,发布订阅和队列就没什么关系了,引入了一个新的概念那就是主题。比如我的微信公众号「代码宇宙」就是一个Topic,你关注我,小明也关注了我,小红也关注了我,那么我们就是一个发布订阅的关系, 我发布文章就会推送给你们三个人,你如果取关了.....那么我发布文章就不会再推送给你,即使你重新关注,你也收不到我之前的推送了。

3.搞懂谁是提供者

要使用JMS就必须有一个人站出来,管理会话、队列、主题等繁杂工作。从 JavaEE 1.4开始,必须在所有 JavaEE 应用程序服务器中包含 JMS 提供程序。

以下是常见的JMS提供者程序列表

  • Amazon SQS's Java Messaging Library
  • Apache ActiveMQ
  • Apache Qpid, using AMQP
  • IBM MQ
  • JBoss Messaging
  • 等等等等

4.什么是同步消费和异步消费

在JMS中,消息消费可以通过两个方式来实现。

No.1同步消费

在同步消息消费中,订阅者/接收者通过调用receive()方法从目的地请求消息。在receive()中,如果消息在给定时间内没有到达,方法将阻塞直到消息到达或超时。就像普通的带有返回值的java方法调用一样。

No.2异步消费

在异步消息消费中,订阅者可以向消费者注册(或订阅)为消息监听器。消息侦听器与事件侦听器相同,每当消息到达目的地时,JMS提供者将通过调用侦听器的onMessage()方法来传递消息,该方法将对消息的内容起作用。

5.JMS 消息组件

JMS Message 即JMS 消息被用来在系统间进行通信。JMS消息具有简单的格式,但是非常灵活,通常包含以下三个部分。

No.1 消息头部(Message Header)

JMS 消息提供很多预定义字段,这些字段包含客户机和提供者用来识别这些消息的关键信息。 – JMSDestination – JMSDeliveryMode – JMSMessageID – JMSTimestamp – JMSCorrelationID – JMSReplyTo – JMSRedelivered – JMSType – JMSExpiration – JMSPriority

No.2 消息属性(Message Properties)

在消息属性中,可以创建和设置消息的属性。

消息属性是由应用程序设置或读取的自定义名称值对。

消息属性对于支持过滤消息很有用。

JMS API提供了一些提供者可以支持的预定义属性,需要注意的是消息属性是可选的。

No.3 消息体(Message Body)

在消息体中,JMS API定义了五种消息体格式,它们也被称为消息类型,允许以多种不同的形式发送和接收数据,并提供与现有消息格式的兼容性。它基本上由从JMS发送者发送到接收者的实际消息组成。不同的消息类型有:

文本消息:由javax.jms.TextMessage表示。它用于表示一个文本块。

对象消息:由javax.jms.ObjectMessage表示。它用于表示一个java对象。

字节消息:由javax . JMS . Bytes消息表示。它用于表示二进制数据。

流消息:由javax.jms.StreamMessage表示。它用于表示java 基元值的列表。

映射消息:用一组关键字或值对来表示。

5.必须清楚在哪用

说了这么多,到底在哪用得到呢?应用场景才是技术的灵魂,JMS的应用场景其实随处可见,举几个例子。 No.1 异步处理

用户注册成功后需要发送邮件或者是短信,这个时候就可以使用消息中间件的点对点模式来实现,用户系统无需关心邮件或者短信发送结果,仅仅需要将需要发送的邮箱或者手机号通过消息传递给专门处理消息发送的系统即可。 No2.应用解耦

订单和库存系统是两个相爱相杀的系统,订单创建离不开库存操作,如果订单系统直接调用库存系统那么势必造成模块间的强耦合,导致系统复用性、健壮性变低,使用了消息中间件后关系发生了如下变化。 订单系统->库存系统(强耦合)

订单系统->消息中间件->库存系统(解耦成功)

No3.流量削峰

比如,系统举行秒杀活动,热门商品。流量蜂拥而至 100件商品,10万人挤进来怎么办,10万秒杀的操作,放入消息队列。秒杀应用处理消息队列中的10万个请求中的100个,其他的打回,通知失败。流量峰值控制在消息队列处,秒杀应用不会瞬间被怼死,变化如下。

用户请求->秒杀应用

用户请求->消息队列->秒杀应用

No.4 日志处理

错误日志->消息队列->日志处理

用户行为日志->消息队列(kafka)->日志的存储或流式处理

说明:日志处理 可是 kafka的强项,大数据的日志处理非它莫属,我没用过,只知道它很强大。非常强大。

No.5 纯粹的消息通讯

本文不以任何MQ讲解的原因是,MQ 仅仅是 JMS 中的一部分,理解 JMS 规范后,消息中间件还不是手到擒来?

2020.04.16 晚

保持好奇的心,也许明天再见,晚安。