APP下载

一种面向消息的中间件的设计与实现

2019-03-28孙弋温迅

物联网技术 2019年3期

孙弋 温迅

摘 要:中间件是位于硬件操作系统和应用之间的通用服务。基于远程调用的中间件技术已广泛应用于各个领域。但介于其同步通信、客户端/服务器强耦合且只能进行点对点通信的问题,其应用始终有相应局限。面向消息的中间件因其忽略平台异构性、异步通信等良好特点恰好可以解决以上问题。利用SUN公司提出的JMS规范,设计消息模型用于通信,通过Java NIO事件驱动的编程模型实现异步通信,最后实现一种面向消息的中间件系统,并给出了该消息中间件在某高校选课系统中的良好应用。

关键词:消息中间件;消息服务;消息队列;异步通信;JMS规范;Java

中图分类号:TP311.1文献标识码:A文章編号:2095-1302(2019)03-00-04

0 引 言

随着企业系统中分布式架构的普及和系统的不断扩大,在异构和分布环境下完成企业的业务管理、数据共享和数据传输已成为行业的焦点,这种环境下,中间件技术应运而生。CORBA(公共对象请求代理体系结构),DCOM(分布式组件对象模型),RMI(远程方法调用)等以远程调用为主的RPC(远程过程调用)中间件技术已广泛应用于各个领域[1],但是面对愈加复杂的分布式系统,这些技术的局限性也愈加明显:

(1)同步通信,客户端发出请求后,须等待接收服务器的响应结果才能继续执行;

(2)客户端与服务器强耦合,客户端和服务器必须同时正常运行;

(3)点对点通信,只有一组客户端和服务器的通信。

面向消息的中间件(Message-Oriented Middleware, MOM)较好地解决了以上问题[2]。在消息中间件中,区别于传统的远程通信客户端和服务器的概念,通信的两端分别为Producer(生产者,发送消息的一方)和Consumer(消费者,接受消息的一方)。生产者将消息发送到中间件服务器中,中间件将消息通过消息队列进行管理[3],在合适的时候再转发给消费者。这种模式下发送者和接收者之间是异步的,二者生命周期未必相同。同时,一条消息的接收者也不一定唯一,对于一个消息可以有多个接收者。

面向消息的中间件系统为企业提供数据传输服务已经多年,但始终没有统一的标准[4]。这使得各中间件厂商产品的实现和接口各异,不同厂商中间件系统之间难以实现互操作和无缝连接。在SUN公司提出Java消息服务(Java Message Service,JMS)规范后有所改观。

本文深入研究了SUN公司的JMS规范,同时在此基础上,基于JMS规范设计实现了中间件系统,并给出一个在高校选课系统中消息中间件的应用实例。

1 Java消息服务

Java消息服务(JMS)是由SUN公司提出的消息中间件规范。因此JMS规范只是一系列统一的接口,并没有具体实现。用户可根据自己的需求对JMS接口进行实现,因为该接口与消息提供者无关,因此客户端的应用程序可在不同机器和系统中移植[5]。同时还可结合用户实际业务而不同实现,以达到满意的效果。

1.1 JMS通信方式

JMS提供客户端与服务器的同步和异步连接,并在任何时候可对消息进行传送和储存转发。消息传输中支持两种截然不同的通信模型:点对点模型和发布/订阅模型[6]。

(1)点对点模型:使用Queue(即队列)。消息从一个生产者传送到一个消费者。在此传送模型中,消息目的地是一个队列。消息首先传递给队列目标,再将消息从队列发送给注册到此队列的消费者。向队列发送消息的生产者数量是没有限制的,但每个消息只能由一个消费者消费。如果没有已注册到队列目标的消费者,队列将保存接收到的消息,当消费者注册到队列时再传递给该消费者。点对点模型如图1所示。

(2)发布/订阅模型:使用Topic(即主题)。消息从一个生产者传送到任何数量的消费者。在此传送模型中,消息目的地是一个主题。消息首先传递给主题目标,再传递给订阅此主题的所有活动消费者。向主题对象发送消息的生产者的数量没有限制,并且每条消息都可发送给任意数量的订阅者[7]。主题目标也支持持久订阅的概念。持久订阅意味着消费者已注册了主题目标,但该消费者在消息传递时可能处于非活动状态。当这位消费者再次进入活跃状态时,会收到此信息。发布/订阅模型如图2所示。

1.2 JMS消息数据结构

在消息中间件中,通信的两端通过消息传递信息。JMS消息对象是应用程序之间通信的基本单元。JMS消息由消息头、消息属性和消息体组成。消息头描述了消息的创建者、创建时间、数据的有效长度、消息的目标队列或主题的路由信息。属性由客户端定义和设置,消息体是消息的主要部分,它描述消息的内容。JMS消息模型如图3所示。

(1)消息头:所有JMS消息都支持统一的消息头域,消息头包含标识信息和路由信息。一个完整的消息头将会传送给所有接收消息的JMS客户端,但不会传送给非JMS客户端。

(2)消息属性:可认为消息属性是附加的消息头,用来支持JMS消息构建工具需要的属性值。为消息提供了一种附加可选择的消息头机制。附带应用获其他数据,用于消息选择器。

(3)消息体:JMS根据要携带的消息类型,规定消息中间件必须支持6种消息接口类型,但JMS并未定义这几种消息接口的实现方式。因此允许消息提供者以自己的方式实现和传送消息。这几个接口分别是Message及该接口的5个子接口TextMessage,MapMessage,StreamMessage,ByteMessage和ObjectMessage[8]。

1.3 JMS编程模型

在JMS编程模型中,JMS客户端通过消息服务进行消息通信。消息生产者向消息服务发送信息,同时消费者从消息服务中接受这些信息。整个通信过程使用一组JMS接口的对象来执行。

在JMS编程模型中,JMS客户端使用ConnectionFactory对象创建一个连接对象Connection,该对象用来向消息服务发送消息或接收消息。创建连接时,将分配通信资源。大多数的客户端均使用同一个连接对象来进行所有的消息通信。

接下来通过连接对象创建Session会话对象。Session是一个用于生成和使用消息的单线程上下文对象。用于创建通信的MessageProducer(生产者),MessageConsumer(消费者)和Destination(消息目的地),并为发送的消息定义顺序。该对象通过大量的确认选项或事务来支持可靠传输。

发送消息时,客户端使用MessageProducer指定Destination對象。消息生产者可设置默认传送模式(是否持久化)、优先级和有效期值,对发往消息服务的信息进行控制。

接收消息时,客户端使用MessageConsumer对象从指定的Destination对象接收消息。接收过程中可使用消息选择器来接收消息客户端感兴趣的消息。

消费者支持同步或异步消息接收。异步接收时可向消费者注册MessageListener(消息监听器)。当会话线程调用MessageListener对象的onMessage()方法时,客户端将接收该消息。JMS编程模型如图4所示。

2 消息队列中间件的实现

2.1 消息队列技术

消息中间件采用消息队列技术和基于消息传递的异步通信机制。在分布式和异构环境中,传统应用程序之间的相互通信需要双方同步执行。 各系统应用间耦合性过强,在消息中间件中使用消息队列技术,可大大减少程序之间的耦合度,应用程序只需发送一条消息后可继续操作。接收方应用程序也无需监视整个接收过程,只需从队列中读取消息并对其进行处理即可。

2.2 基于JMS的消息中间件的体系结构

消息中间件在结构上分为两个部分,客户端和服务端。其中包含了一个JMS应用必备的4个模块,分别是JMS客户端、JMS提供者、消息和JNDI服务。JMS消息中间件体系结构如图5所示。

其中消息中间件服务包含JMS服务(消息服务)和JNDI服务(命名对象服务)。JMS规范中提供两种受管对象,ConnectionFactory和Destinatio,即前文提到的连接工厂和消息目的地需要由JNDI命名空间进行管理。JMS受管对象如图6所示。

2.3 JMS消息中间件的实现

2.3.1 服务器端的实现

(1)服务器的实现

JMS服务器是消息中间件服务的核心。服务器启动时,初始化服务器,读取主机地址、监听端口、服务类型等相关参数,并启动相应的组件。JMS Server结构如图7所示。

通过读取到的相关参数,创建ServerBroker组件。同时监听相关端口中来自客户端的请求。ServerBroker组件用来处理与客户端的消息通信;JMS Server的具体实现的主要API见表1所列。

最后,将启动的ServerBroker组件保存在列表当中,该列表保存所有当前活动的客户端连接。

消息服务可通过多种方式实现消息通信,如TCP,UDP,RMI,HTTP等,通过定义ServerBroker接口,规范连接过程并将具体通信方式做不同实现。

(2)ServerBroker接口

该消息服务的ServerBroker采用TCP方式进行通信,调用start()方法后,创建一个ServerSocket监听客户端请求。收到连接请求后,ServerBroker会创建一个新线程,并通过ServerSocket的accep()方法获取客户端socket与之通信。ServerBroker API见表2所列。

(3)Transport类的实现

ServerBroker组件通过Transport类实现消息传递,该类在一个新的线程当中,通过其send()方法轮询的发送队列中的消息。该线程将一直处于轮询状态直到调用了stopTransport()方法。Transport API见表3所列。

(4)JNDIServer类的实现

JNDI服务主要用于管理受管对象ConnectionFactory和Destination。初始化JNDI服务后,TCPConnection方法创建ServerSocket用来监听客户端的请求并与之建立连接。最后通过管理器通过bind()方法绑定JNDI受管对象和消息目的地。同时客户端可通过lookup()方法获取已注册的受管对象。JNDI Server见表4所列。

2.3.2 客户端API的实现

客户端实现由JMS API定义的标准接口。 本系统的JMS客户接口的主要实现如下:

(1)Connection对象

Connection是JMS客户端和JMS消息服务之间处于活动状态的套接字。Connection在创建客户端时对其可指定唯一的客户端标识符。连接创建后,它处于挂起模式,此时不提供任何消息。直到客户调用 start()方法开始消息传递。JMS针对两种消息模型定义了两种连接对象。我们在此实现QueueConnectionImpl和TopicConnectionImpl。主要功能为获取Session对象和启动关闭连接。

(2)Session对象

Session对象是通信中消息的创建者、生产者、消费者、主题和队列的生产工厂。针对JMS规范,创建实现类SessionImpl,用于创建不同类型的消息,并返回相应Message对象;用于创建通信的客户端、生产者、消费者;用于创建消息目的地和消息模型。

(3)MessageProducer对象

MessageProducer对象由Session对象创建,主要用于向对应Destination发送消息。其中主要实现其send()方法。通过设定目的地、传送方式、优先级等发送消息。

(4)MessageComsumer对象

MessageConsumer是Session对象所创建,用于接收来自Destination 的消息。主要实现receive()方法用来接收消息。receive()方法中可配置消息选择器用于配置接收期望的消息。同时可选择通过或异步的接收消息。对于同步接收,采用轮询的办法;对于异步接收,将会注册一个消息监听器MessageListener对象,并通过其OnMessage方法来处理异步消息。

2.3.3 消息模型的实现

消息模型按照JMS规范中消息结构的定义对其进行实现。消息头中,Messageheader类中包含了Destination,MessageID,Priority等消息识别信息和路由信息。JMSMessageID唯一标识了队列或主题中的每一个消息。

2.3.4 消息队列中间件在高校选课系统中的应用

高校选课系统中的主要需求是选课时对课程余量的并发争抢。有限的课程数量面对瞬时的高并发请求,此时就可利用消息中间件良好的异步通信特性来实现。当用户点击选课按钮后,将请求发送至中间件服务器。队列管理器开始将请求加入课程选课队列,成功则告知正在选课,否则客户端响应选课结束。对于队列中的选课请求则进行课程余量减库存处理,并记录结果。选课过程完成后标记选课结束,并清空选课队列,避免重复判断和处理[9-10]。

用户轮询结果,如果选课结束且该用户选课失败,则跳转到选课结束页面,否则继续等待直到成功。后面选课结果的持久化,则是选课逻辑中需要操作的業务。消息中间件在高校选课系统中的应用实例如图8所示。

4 结 语

消息中间件在大型企业分布式应用中具有丰富的应用。相较于通过远程调用实现服务传递的系统,面向消息的中间件提出了一种灵活、扩展性好且使用简单的通信模式。可为高并发需求提供缓冲,也可忽略平台异构性,为分布式应用提供简单的中间桥梁。极大地增强了系统集成的简易程度和扩展性,降低了系统更新维护成本和难度,使系统更加高效运行。目前,面向消息的中间件系统已成为中间件系统中发展最快体系,有着非常广阔的前景。

参 考 文 献

[1]陈旭东. 基于CORBA技术的综合电信网管系统的构建[D].北京:华北电力大学,2005.

[2]张靖,邱云.JMS信息发布异构平台应用研究[J].煤炭技术,2010,29(1):209-211.

[3]何双元. 高并发下消息队列模型的研究与应用[D].武汉:武汉理工大学,2015.

[4]朱方娥,曹宝香.基于JMS的消息队列中间件的研究与实现[J].计算机技术与发展,2008(5):172-175.

[5]汪涛. 基于SOA架构的中间件应用集成研究[D].西安:西安电子科技大学,2011.

[6] 佚名.Java Message Service API Rev[EB/OL].[2002-04-08].http: //java.sun. com/products/jms/.

[7]李艳春,李新,焦文彬.分布式信息系统中数据交换平台设计与实现[J].计算机工程与设计,2012(7):2640-2645.

[8]珍兆科.Java EE 6开发手册·高级篇[M].北京:电子工业出版社,2014.

[9]王迎.自动化测试平台的设计与实现[D]北京:北京交通大学,2015.

[10]邵作镇,万晓冬.基于STAF的软件自动化测试研究与应用[J].电子科技,2010(7):9-11.