技术访谈:消息驱动的架构与SOA
Sunila Srivatsan - 首席技术专家
|
Sunila Srivatsan 是《 BEA WebLogic Workshop 8.1, Simplifying Java Web Applications and J2EE , 2004 》( SAMS 出版社)的作者之一, 12 年来,她在信息技术领域扮演了多个重要的角色。她的声誉来自于和各种不同机构的技术和策略合作。这些机构包括:几十个进入财富 500 强的公司、美国本国和外国政府机构以及国际客户。她的专业范围涉及:项目架构、设计和开发、生命周期管理、教育培训、技术课件开发以及技术调查。从 2000 年开始, Sunila 针对 BEA 培训服务的技术文章涉及了所有基于 Java 的 BEA 产品。她广泛的技术能力以及从客户的利益出发来为他们解决问题的能力,一直使她深受客户喜爱。在过去的几年中, Sunila 在 eWorld 和 JavaOne 会议上提交了关于多个核心领域的技术论文。 Sunila 曾取得数学学士学位( 1992 )和计算机科学专业的研究生学位。
|
访谈内容
能否告诉我们一些关于您自己以及您在BEA所做工作的内容 ?
我在 BEA 工作了大概 5 年,一直是做培训服务方面的工作。我使用过 BEA 的所有产品——现在我们称之为平台套件),如 WebLogic Server 、 Portal 、 Liquid Data ——这个是最新产品,以及基于消息传递框架的 WebLogic Integration 。
您对消息传递有什么看法?
它非常有趣。当我们谈及两个应用程序相互通信、分别向对方传递消息时,涉及到好几个障碍。首先,主要的障碍是需要把这两个应用程序连接在一起,这就意味着我们需要同时使两个应用程序活动。比如说我们有这样一种需求或遇到这样一种情况,就是我们有一个应用程序,需要用它发送同样的信息给多个不同的应用程序,我们将先向一个应用程序发送信息,然后向另一个发送信息。由于信息相同,这将会有某种程度的冗余出现。在我看来,消息传递本质上是一个框架,它使这两个应用程序能够克服所有的障碍相互通信。在一些机制当中我们并不担心这两个应用程序同时活动,但同时我们还想使它们就像连接在一起那样。这就是消息传递。我想说的是它是一个框架。这就是我要说的消息传递。
实现消息传递的方法有哪些?
在这里我将举一个例子。首先,关于消息传递框架的工作方式,我想用的例子是某个运输公司。以联邦快递( FedEx )公司为例,作为消费者,当我们要寄送包裹时,比如说我想给您寄点儿什么东西时,需要做的就是必须首先选择合适的包装。 FedEx 会提供信封、盒子或者其他包装用具。首先根据要邮寄的东西来选择合适的包装,然后把您的名字、地址写上,付钱,之后把它寄送给您的责任就从我这儿转移到了 FedEx 。在消息传递领域,也是如此。但是不再是 FedEx ,而是面向消息的中间件( Message-Oriented Middleware ),即 MOM Server 。寄送包裹的那个人——我们称这个特定的客户端为生产者,当然消息需要传递给某个人所以这一端是消费者。但是,它并不像说“噢不错,我们有了生产者,也有了消费者”那么简单。在消息传递的领域里,有几个障碍需要我们克服,其中一个我在前面已经提到过,就是一个应用程序需要向多个应用程序发送同样的信息。在消息传递领域,您可以使用两种策略:一种是使用对等式,它是真正的点对点;另一种是使用公共订阅,它是一个应用程序向多个应用程序发送同一个信息。鉴于有两种策略, MOM Server 有不同的组件来支持这两种不同的策略——我们通常称这两种策略为域。
在哪种用例中点对点方法 相对公共订阅方法更适用?
我想再举一个例子。首先,我刚才所举的 FedEx ,是一个点对点的例子。很显然我并不想把我的邮包切成几份送给几个人。这就是点对点。我想以 BEA 为例来说一下公共订阅。比如我们正在搞针对客户的宣传活动,我们说“好了,我们有 100 个不同的礼品包,让我们随机挑选 100 个客户,然后把礼品包送给他们。”这有点像是发布 / 订阅( publish/subscribe )模式,其中有一个大公司——如 BEA ——发送相同的信息给多个不同的客户。对于软件领域而言,就像我们收到的垃圾邮件。我相信您一定能够理解,因为有很多这样的公司,如果您订阅某个杂志——让我们以 TheServerSide 为例——您订阅,告诉这个应用程序“嗨,我对您的内容感兴趣,我想知什么新的内容”,因此您订阅了这个杂志,以后每个星期或每隔一个星期您都将收到一些电子邮件,说是您感兴趣的新信息。这也是发布 / 订阅模式。就是将一个信息送给订阅某个主题或者某个杂志的所有人。以上这些例子就是关于点对点和发布 / 订阅的。根据应用程序的需要以及您想要把一个信息发送给一个应用程序还是给多个应用程序,来决定采用点对点还是发布 / 订阅模式。
这些概念是如何映射到 Java 的 ?
这是个很好的问题,因为对于消息传递来说,首先,您不需要真正去编写自己的代码。 J2EE 提供了 JMS 规范和 Java Messaging Service ,这意味着什么呢,就是已经有了被明确定义了的一套接口、方法和 API 。如果有一个供应商说:“嗨,我实现了或者我通过 J2EE 认证”,您需要关心的就主要是可移植性了,因为 JMS 是 J2EE 的一部分。 JMS 仅仅是一套 API ,您需要对消息的定义。如果一个生产者创建一个信息但是消费者无法理解它,那么这对任何人都没有帮助。您需要一个消息结构,来应用于这个消息。您需要发送和接收消息的方法。这些都是 JMS 提供的。它之所以和 Java 有关,是因为,显然我们谈论的是在 J2EE 中进行创建,我们在谈论 J2EE 规范。这也是消息传递适用于 Java 领域的地方。
开发人员如何从同步方法跳至消息传递 ?
从我个人来讲,我首先想到的是,我的逻辑是否是事件驱动的。当我说“好吧,我需要一些事件驱动的逻辑,因此我实际上并不打算调用方法,但是如果发生了什么事情,我需要发送某种消息或者某种信息,基于此我将触发某段代码。”这就是需要考虑异步的第一信号。当我们开始考虑异步时,要考虑的第一件事情是,有个叫 JMS 的东西。这是我首先想到的事情。我想到的第二点,也是我认为应该当作经验法则的是,消息传递属于处理领域。我这样说的原因是处理或者创建这些处理定义的实现在今天非常流行,但还没有成为范例。关于处理,我要举的例子是信用卡公司。我想我们都能理解这样一个例子,因为我们都曾经历过。无论我们拨打 800 ,还是通过表单发送某种信息,表示我们有兴趣获取一张信用卡,我们都不能得到信用卡,因为我们将被告知需要三个星期。为什么?因为信用卡公司将利用外部资源,检查信用历史,以及获取信用评分。根据信用评分,他们会说:“不,这太糟糕了。我要拒绝它。”或把它送给一个主管做最后的决定:“噢,这不太好,因此我将给它一个低信用限制。”这就是我们谈论的处理。如果我想要做类似的事情,我不可能异步完成。因为信用卡公司的系统可能出现故障,而不可能让客户拿着电话等候一个月。我需要某种可以异步处理这些问题的机制。这是关于消息传递您肯定会想到的东西。但我真正想谈的是底层技术,它的内部是怎样的——如果是构建 web 服务的话,还有那些供应商在干什么,他们是如何实现异步行为的,最终您会发现其实就是在 Java 世界中使用 JMS 。
在JVM 的内部使用JMS 的原因是什么, 或者说它主要是用于远程异步通信?
我可以举出多个例子来说明 JMS 是有用的,但是还有多种其他的技术可以在 JVM 内部使用。我想到的一个例子是 JMX ——我现在谈到的是 Java Management Extension ——它是一个相当大的规范。今天大部分的供应商都在使用它来实现他们的基础架构。我要举的例子是针对管理员的。当我和管理员交谈的时候我常常会遇到问题,因而需要发送通知,但是我们并不想在夜里被传呼之类的事情打扰,就如手机或者其他类似的东西那样。我们真正想要的是,有一个中央储存库,所有的消息都被发送到这里,然后在第二天早上浏览这个存储库看看都有些什么事情。我知道这用 SNMP 之类的就可以轻松实现,但是假设我们没有 SNMP 以及别的类似的工具。我们拥有 J2EE 提供的所有规范,如何实现我们想要的呢? JMS 是一种非常好用的技术。您要做的就是编写阅读这些日志文件的 JMS 客户端,然后向队列或者主题( topic )发送一个消息。第二天早上,管理员仅仅浏览一下就行了。您可以编写 JMS 客户端或者某种代码来使管理员能够浏览消息。也许一些供应商也提供同样作用的实用程序。我们常常谈到应用程序之间的通信,但是有时您仅仅因为资源稀缺才使用它,而您没有合适的产品来实现您想要的。我觉得这应该是 JMS 可以使用的时候。
在J2EE 中异步消息传递 有哪些方法 ,如何进行选择?
首先,对于异步消息传递,并不真的需要使用 JMS 。我可以编写自己的代码,还可能使用一个数据库来保存那些我想要的特定信息。不管多难或者多容易,您都不想这样做,因为首先要编写所有代码,然后还要维护它。可移植性是一个大问题,因为当我们自己编写代码的时候,我们将优先使用一些专有类,因为我们将不会从头编写每一行代码,而且我们希望远离最原始的基础,特别是当我们谈及的是 J2EE 应用程序的时候。既然这样, JMS 是否是最好的,或它是否是所能采用的最好方法?当然,因为它是 J2EE 技术的一部分,而且正如我说的那样,我不是在谈实现。我不是说您必须编写一个 JMS 客户端,我是说如果您在编写异步 web 服务,您也许想知道您将之作为服务提供者,来发布该 web 服务的供应商是如何实现它的。这就是我之所以说 JMS 非常流行仅仅因为 J2EE 1.3 应用服务器默认实现 JMS ,是因为 EJB ,您通过 bean 得到消息。您并没有真的去买更多的产品,仅仅使用已有的,涉及 J2EE 时购买一个应用服务器。那么为什么不最大限度地利用它呢?这就是我希望 JMS 被经常使用的地方。
J2EE Servers 是如何实现 MOM 或面向消息的中间件的呢?
我们谈到 J2EE 应用服务器实现或者 MOM Servers 。在前面当我谈到点对点和发布 / 订阅模式的时候,我说消息被发送到 MOM Server ,并把它和 FedEx 相类比。这个 MOM Server 是什么?拥有一个 MOM Server 意味着什么呢?在点对点当中,当一个生产者发送这个消息时,在 MOM Server 上必须有组件存储这个消息,因为我们也注意到了其他应用程序没有激活的障碍,而且我们使用的组件术语叫队列。而在发布 / 订阅中,使用的组件是主题。有了队列和主题 , 就必须有基础架构来维护它们。当我们说到应用服务器实现或者叫作消息传递服务器时——有时候不是应用服务器而仅仅是消息传递服务器,它后面的整个理念是它有一个内置的基础架构来创建这些队列、主题以及与这些 MOM Server 的连接,因此生产者能够发送消息,消费者可以接收消息。正如我举的例子中 FedEx 为您保存包裹,同样,应用服务器也需要有一些永久性存储器这样信息就不会丢失,这就是在应用服务器内部实现 MOM Server 的真正含义。
WebLogic Server 如何实现消息保证送达 ( guaranteed message delivery ) ?
非常精彩的问题。我们常常谈到消息传递,我曾接触到很多不同的客户,他们经常问我如果消息丢失了会怎样。这是 JMS 的真正重要部分。我将先说 JMS ,然后再谈 WebLogic ,因为 JMS 的规范内部有一个内置的概念或者功能,称为消息保证送达。它实际就是说,如果您说自己是一个支持或实现 J2EE 技术和 JMS 的供应商,您就必须支持消息保证送达。 WebLogic 支持它的方法是让您可以控制或者配置存储这个消息的地方。我们给出两种选择,文件存储和数据库存储。当您说“好,我想存储它”的时候, WebKLogic 自动说,“这是个消息,不能够丢失;它必须被发送出去。”然后自动用这两种存储当中的一种来存储它,显然您可以控制您想要的表格以及类似的东西。这就是 WebLogic 实现消息保证送达的方法。
采用同步方法的时候如果 被呼叫的服务器出现故障,采用异步消息传递方法会怎样?有对集群和故障恢复的支持吗 ?
真的是非常有趣,如果您三年前问我这个问题,我肯定会说:“我想我们没有。”但是这几年来, JMS 取得了很大的进展,事实上现在 JMS 有了集群。但不同的厂商实现的方式不尽相同。我将以 WebLogic 为例。我们有负载平衡和故障恢复,但是,涉及 JMS 之后很难将发送一个消息给集群中的三个服务器。让我们以点对点为例,前面我提到一个消息只能被一个特定的 JMS 客户端消费。我发送这个消息给三个服务器,是因为我担心故障恢复或者服务器 A 可能出现故障。但是,在这种情况下,还有另外一个问题。如果同一个消息同时在三个服务器上出现,如果同时有两个用户,一个登录服务器 A ,一个登陆服务器 B ,会出现什么情况呢?我们不希望这个消息同时被两个消费者处理,因为这是点对点的。我们所做的是,发展了一个叫做 Distributed Destination 的概念。您有一个分布式队列和一个分布式主题,这一切意味着这些物理队列或物理主题的一个逻辑分组,而这个 Distributed Destination ——它是一个逻辑目的站——有发送消息的算法,无论是在点对点模式中发送给某个队列,还是在发布 / 订阅模式中发送给所有的主题——我们在发布 / 订阅模式中并不在乎。这就是域的意义。这种逻辑就如一个对象内置于 Distributed Destination 组件中。开发人员不使用物理目的站,而简单地使用 Distributed Destination ——或者我应该说这个 Distributed Destination 的 JNDI 名称——然后 WebLogic 在内部进行负载平衡。有了故障恢复,就有了一个称为迁移的概念,所有这些意味着可以预配置,即:如果有源有目标或目的站,就可以进行预配置。如果源出现故障了,您仅仅需要简单地说“那么,现在向目标发送这些消息”,然后目的站或者目标服务器就去处理这些消息。当我说您必须击中( hit )迁移时,是说您可以通过创建事件或者类似的东西把它自动化。它是一个可用的预配置的选项。
JMS 是否能够用来解决极高流量问题 ,比如在证券交易中?
事实上,这也正是我想举的例子。我有过一个有趣的经历,那是相当长一段时间以前的事情了。那是在 J2EE 还没有流行之前,在一个应用当中有一个数据库和一大堆应用程序,这些应用程序需要信息时会查询数据库,并且无论什么时候它们需要信息都翻动数据库。大家知道,通常我们都想把对数据库的请求控制到最少。设想一下有 50 个应用程序说,我想要那条信息,然后盯着同一条信息。这会对数据库造成压力。我要说这不是什么好的实践,因为这时会出现性能问题。我要说的是,这是 JMS 派上用场的地方。我将举您提到的证券的例子。我们使用证券应用程序并提供一个符号。显然我们知道有成千上万个符号,但我们并不关心其他的。也许我是个交易商,我关心那些符号当中的 20 个。这是一个很适合用消息传递框架实现的应用程序,我将创建不同的主题,而那 20 个我感兴趣的符号,我将订阅它们,以便获得关于它们的信息。我不真正关心另外 980 个符号。这就回答您的问题:我想消息传递能够起到作用。您会想起消息传递的地方之一是事务多发之处。我不是说不需要同步,我的意思是,首先必须判定这个消息对许多应用程序来说是否有用,然后也许要用到消息传递,但如果只是一个应用程序随机查询数据库,可能还用不上消息传递。
您如何看待消息传递适合面向服务架构( Service-Oriented Architecture , SOA) 这种情况 ?
首先, SOA 现在是个重要范例。我看到很多的客户实际上都在使用这个架构来构建他们的应用程序,但是对 SOA ,我们常说它是 web 服务,其实 SOA 不仅仅是 web 服务。它还有别的组件。但是我暂且假定 SOA 等同于 web 服务,因此我下面要谈的都是 web 服务。 Web 服务是最先的和最重要的内容。我有两个服务,我在不同的操作系统——假如说是 BEA 和 Microsoft 的 .NET 服务器——上实现这两个服务。但是,我又遇到了一个问题,假如这两个 web 服务不是同时活动呢?假如它们不能同时相互通信呢?假如由于这两个服务当中的一个需要升级而需要一种机制来升级这些应用程序之一呢?此时我就遇到了问题。尽管我们关注的是 web 服务,但是在内部进行的——也正是 BEA 正在做的——是我们在使用 JMS 。在内部有消息驱动的 bean ,我们使用它们来实现这两种服务之间的异步。我确实说过 SOA 不等同于 web 服务,其他能实现的东西是什么?我前面说过处理的定义。那个我提到批准信用卡的例子,我可以建立针对它的服务。其中一个服务就是“获取信用报告”。显然该服务是异步的。如何实现它呢?我需要用到 JMS 或者消息传递框架。事实上,以我的经验和我的看法, SOA 将使 JMS 更加流行,相比过去仅仅因为在 J2EE 领域我们需要一个框架来实现所有服务的异步,才使 JMS 流行而言更流行。显然我们谈论的 web 服务也涉及非 J2EE 领域,但在 J2EE 领域,最好的方法就是使用 JMS ,因为有基础架构。因此,我们不打算搞一些新的东西,我们并没有处在不得不说“噢!我们遇到了问题,需要想出一个解决方案。”的境地,我们有解决方案,我们只需要使用它。这就是 JMS 很受 SOA 欢迎的原因。
WebLogic 的消息传递 提供 了什么?
首先, WebLogic 确实实现了 JMS 。所有我们提到的,队列、主题、连接,都是有关一个完善的 MOM Server 的。但是我也提到,我们有集群。有某些功能非常有用。一个就是流控制。客户关注的一个重要内容就是性能:“好吧,这听起来很好,运行起来如何呢?”我们有流控制,因此服务器不会出现每秒有多个消息同时进入的情况。可以设定一个阈值来控制,之后服务器会说,好的,我将减少进入的数目。还有一个非常有用的功能,称为消息传递桥。 WebLogic 是一个 MOM Server 。假定我使这个应用程序跨地区,比如跨纽约、波士顿和芝加哥。我不想使用同一个 MOM 服务器横跨这三个地区,因为我遇到了性能问题。我们有消息传递桥。不管您怎么配置,它都可以使 MOM 服务器相互通信,使队列或主题中的消息同步。这有什么用呢?您现在有了一个 gatekeeper 。您可以让纽约服务器发送消息给该 gatekeeper ,芝加哥和波士顿服务器也同样发送消息给它,这个 gatekeeper 其实就成了中央储存库。这是一个内置功能。不仅如此,假如我有一个非 J2EE 的消息传递框架,我要想使用它的话也可以用到消息传递桥。因为消息传递桥也允许您连接到一个非 J2EE 的 MOM Server 上,或者我应该说连接到一个消息基础架构上。这是另外一个可用的功能。您可以运行多个服务器,然后让这些队列基于 Distributed Destination ,我们有池的概念。它和我们所说的所有其他的池都类似,而惟一的区别是,不管是发送还是接收消息可以用多个线程。还有几个巧妙的功能,但是我觉得最受欢迎的是集群功能。
未来的 JMS 和 WebLogic JMS 版本 都有哪些 重要的 新功能?
有了 JMS 规范 , ,接下来要面对的问题之一就是公共接口和公共 API 。现在,有针对队列的 API ,也有针对主题的 API ,正在进行的是二者的公共 API ,我想这仅仅是为了使开发人员的生活更轻松。 JMS 规范中其实有队列和主题的公共 API ,但是 WebLogic 添加了多个新功能。我将提到几个功能并告诉您它们是做什么用的。现在,当您实现 JMS 时,它是一个可使用的组件。您有自己的企业应用程序,然后使用所有这些不同的组件,它们与您的企业应用程序是分离的。它们在服务器配置文件或者类似文件当中。把所有这些信息都包含在您的企业应用程序中是很不错的。为什么?因为当您从一个环境进入另外一个环境中后,一切都在一个程序包中。我们有部署的概念,它是模块化的。我们听说过 Java 模块、 web 应用程序以及 EJB 。现在,您也将听到 JMS 模块的说法。就像其他的部署描述符一样, XML 文件是 JMS 模块的部署描述符。所有您担心的就是这个程序包。但是您仍然有其他选择,因为我们认识到有的客户可能想升级现有的版本,并且不太喜欢使用这种模块化方式,因此依然要单独部署 JMS 。另外一个很酷的功能是存储转发。假如您不想和远程服务器通信,或者您想有一些本地的东西,该怎么办呢?我刚才说了 gatekeeper 功能,现在则是一种我们不得不实现的、要随产品一起提供的功能,我们称之为存储转发。您只需要简单地把它发送给本地服务器。本地服务器将负责把它发送给远程服务器。另外一个巧妙的功能,虽然在那些新功能中并不起眼,但对开发人员来说确实是不小的帮助,就是一个统一的分布式目的站。它意味着针对我刚才所说的分布式队列和主题,您将有一个可以在两个域中都能使用的组件。另外一个很酷的功能是它真正改善了用户界面( UI )。我们很多次听到客户说:“嗨您这个消息传递服务器实现不错,但是我想查看这些消息。可能一个消息应该已经发送出去了,而我想查看一下,是否真的发送出去了,虽然这没有什么意义,但是我想控制这类事情。”我们将提供这种服务。我们改善了 UI 以便可以查看消息。我们还改善了停止和暂停功能——应该说是暂停 - 继续目的站。因而您可能要说,我仅仅想停止处理这些消息一会儿,因为我想处理工作可能不起作用或者任何别的可能的原因。这个功能就在下一个版本的 WebLogic 中。这是一个很酷的功能,我觉得管理员会喜欢它。我们正在努力满足不同人——开发人员、管理员——的需求,使他们的生活更加轻松。其余的都将保留,集群也将被保留下来,当然,我们将实现最新的 JMS 规范。
好的,谢谢。