【中间件技术】第一部分 概述(1) 软件构件与中间件基本概念

文章目录

  • 1.1 分布式软件的基本概念
    • 1.1.1 分布式软件与客户机/服务器模型
    • 1.1.2 分布式软件的三层/多层结构
  • 1.2 软件构件的基本概念
    • 1.2.1 对象到构件的发展
    • 1.2.2 软件构件的特性与相关概念
  • 1.3 中间件的基本概念
    • 1.3.1 中间件的动因
    • 1.3.2 中间件提供的支撑
      • 1. 提供构件运行环境
      • 2. 提供互操作机制
      • 3. 提供公共服务
  • 1.4 互操作的基本原理与实例
    • 1.4.1 互操作的基本原理
    • 1.4.2 互操作实例
      • 1.4.2.1 数据库设计
      • 1.4.2.2 接口定义
      • 1.4.2.3 服务端程序
      • 1.4.2.4 客户端程序
      • 1.4.2.5 编译并运行应用程序
      • 1.4.2.6 分布运行
      • 1.4.2.7 小结

这里介绍分布式软件的基本概念、软件构件的基本概念、中间件的动因与基本概念;利用 JDK 的远程方法调用 ,开发了一个简单的分布式应用程序,通过该例子演示「软件构件与中间件技术为软件开发提供的基本支持」。


1.1 分布式软件的基本概念

1.1.1 分布式软件与客户机/服务器模型

在计算机硬件与 络通信技术的支持下,应用需求驱使计算机软件的规模与复杂度不断增长,软件正变得无处不在,软件所面临的挑战也正在日益加剧,软件开发过程中复杂度高、开发周期长、可靠性保证难等问题日益突出。在这种背景下,软件开发人员不得不在软件开发的过程中寻求更多的支持,以帮助其在特定的开发周期内开发出规模更大、更可靠的软件系统

这一系列关注在上述背景下大型分布式软件系统的开发支撑。原因主要有两个:

  • 随着 络与通信技术的发展,分布式软件的应用越来越广泛,分布式软件在计算机软件应用领域扮演着非常重要的角色。
  • 分布式软件一般比集中式软件规模大、复杂,是软件开发复杂性的集中体现

简单地讲,分布式软件是指运行在 络环境中的软件系统,而 络环境是一群通过 络互相连接的处理系统,每个处理节点由处理机硬件、操作系统及基本通信软件等组成分布式计算有两种典型的应用途径

  • 第一种应用途径是,将分布式软件系统看作直接反映了现实世界中的分布性,例如:当今许多业务处理流程通常呈现一种分布式运作方式,如某生产制造企业,其负责加工制造的工厂可能位于珠江三角洲一带,而负责销售的部门则可能分别位于北上广,这时负责业务流程的软件系统显然也应做相应的分布式处理。
  • 第二种应用途径,主要用于改进某些应用程序的运行性能,使它们比单进程的集中式实现更具有效率,如利用互联 上的大量计算机实现海量数据的科学计算或分析,此时软件系统的分布性并不是现实世界中分布性的映射,而是为利用额外的计算资源而人为引入的。

分布式软件通常基于客户机/服务器 模型。如果一个系统的两个组成部分存在如下关系:其中一方提出对信息或服务的请求(称为客户机),而另一方提供这种信息或服务(称为服务器),那么这种结构即可看作是一种客户机/服务器计算模型。

互联 的许多应用程序都采用客户机/服务器模型,例如 Web 浏览器与 Web 服务器、电子邮件客户程序与服务程序、FTP 客户程序与服务程序等;更一般地,在普通的函数或对象方法调用中,「执行调用语句的子程序」与「实现函数/方法体的子程序或对象」可看作一种客户机/服务器模型,其中实现方是服务器,调用方是客户机

分布式软件与传统的集中式软件的主要区别在于,强调客户端与服务端在地理位置上的分离,这种分离可带来许多好处:

  • 更好的支持平台无关性:客户端和服务端可以运行在不同的硬件(PC、工作站、小型机等)与操作系统(Windows、Unix、Linux等)平台上;
  • 更好的可扩展性:可以在服务端功能不变的前提下,对服务端的程序进行改进或扩充,而这种改进或扩充不会影响到客户端的应用程序。

当然,客户端与服务端的分离也使得软件系统更复杂:

  • 开发人员不得不分别编写客户端和服务端应用程序,并力求保持两者的一致性;
  • 软件系统的调试、部署、维护更加困难;
  • 需考虑更多的可靠性、安全性、性能等软件质量因素。

1.1.2 分布式软件的三层/多层结构

早期的分布式系统基于图1-1所示的两层结构。在两层结构中,简要将软件系统划分为服务器层和客户层,服务器层又称为数据层。这时的系统结构比较简单,就是多个客户端程序共享一个数据库

  • 在服务器层,一般放置一个数据库服务器,上面安装一个数据库管理系统,存放系统用到的持久数据。
  • 三层结构中软件开发的主要工作量在中间层中间层包括除用户界面代码与持久数据之外的几乎所有系统代码,是整个软件系统的核心

    3 3 3 层结构中,客户层和数据层已被严格定义,但中间层并未明确定义。中间层可以包括所有「与应用程序的界面和持久数据存储无关的处理」,假定将中间层划分成许多服务程序是符合逻辑的,那么将每一主要服务都视为独立的层,则 3 3 3 层结构就成为了 n n n 层结构。典型地,可将业务逻辑层分离出实现数据持久化操作的持久层,用于实现对于持久数据操作的封装,从而形成由客户层、业务逻辑层、持久层与数据层构成的四层结构。


    1.2 软件构件的基本概念

    本节从分布式对象的角度讨论软件构件的特性。分布式对象是构成分布式系统的软件构件除了具备一般软件构件的特征外,其重要特征就是分布特性

    1.2.1 对象到构件的发展

    按照面向对象的观点,软件系统由若干对象组装而成,将这一观点延伸至分布式系统,分布式系统由若干分布式对象组装而成。面向对象的精髓之一在于,对象维护自身的状态、并通过消息进行通信,这对于分布式计算环境是非常理想的,但是分布式对象与传统对象相比,有其特殊的特性

    首先,分布式系统由于其规模与分布特性等原因,比集中式系统更容易被拆分给不同的人或团队开发,这就很有可能遇到不同的人或团队习惯使用不同的程序设计语言和环境的情况。但是,这些使用不同语言的人(团队)开发的程序要能够方便的交互,换句话说就是,用不同的语言所写的对象要能够方便的交互。而在传统的集中式面向对象系统中,显然对象之间的交互是局限于某种特定的语言的。从语言这个角度我们可以看到,分布式对象比传统对象面临的环境更复杂,这要求分布式对象比传统对象具备更好的封装特性,比如,要把实现所使用的语言屏蔽起来,对象的使用者看到的是一个跨语言的对象。

    更进一步讲,分布式系统要求分布式对象可以在任何粒度上透明的使用,也就是说,无需考虑位置与实现,不需要考虑具体在哪——是与使用者在同一个进程内,还是在不同的进程内,如果不同又在哪个进程内,或是在哪个机器上的哪个进程内,或者是运行在什么样的操作系统之上等等。这些具体的位置信息,使用者都不希望去过多的关心,另外也不需要关心对象的具体实现细节——如是用什么语言实现的,是不是用面向对象的语言实现的,还是用一个函数库甚至是一个面向对象数据库实现的,都不用去关心。

    传统的面向对象语言中的对象,很难满足上面提到的要求。传统对象的关注点是封装通过继承对实现进行重用——封装提供了一种「将对象实现细节与其他对象屏蔽开的严格方法」,可以大大缓解在面向过程系统中较突出的维护问题;继承提供了一种重用对象实现的简便方法。而分布式系统要求分布式对象要有更好的可插入性,这个要求仅仅依靠传统面向对象的封装和继承是不可能满足的:

    • 首先,要求另一层次上的封装,只需暴露公用接口;
    • 其次,从重用的角度来讲,继承局限于程序设计语言,而分布式系统不太关注于直接重用代码,而是要求能够利用远程所实现的服务。这就是说,分布式系统中的分布式对象和传统的对象不一样,实际上是具有良好封装特性的软件构件

    一般地讲,构件指系统中可以明确辨识的构成成分,而软件构件指软件系统中具有一定意义的、相对独立的构成成分,是可以被重用的软件实体,构件提供了软件重用的基本支持。

    分析传统工业,如机械、建筑等行业,以及计算机硬件产业,其成功的基本模式是符合标准的零部件(构件)生产基于标准零部件的产品生产(组装),其中复用是必需的手段,而构件是核心和基础。这种模式是产业工程化、工业化的必由之路,也是软件产业发展的必然途径,这是软件复用与软件构件技术受到高度重视的根本原因。

    由于关注分布式系统,对应软件构件也关注分布式构件,因此以后论述中不区分构件与分布式对象这对概念,一般提到的构件均指分布式构件,即分布式对象,反之亦然。

    1.2.2 软件构件的特性与相关概念

    与对象相比,构件通常具有如下特性:

    • 构件是一个严格定义的可插入单元:类似于硬件模块,一旦开发完成,就可以方便的用来组装系统。构件一般是基于对象实现的,但也可以不作为对象实现
    • 构件将封装运用到了极限:构件通过封装来隐藏构件的实现以达到:构件的实现语言是未知的,如一个Java客户端不会感觉到所使用的构件是由C++实现的;构件的物理位置是未知的,一个VB客户端不会感觉到所使用的构件是运行在相同的进程内(使用DLL),还是在同一机器的不同进程内,甚至是位于不同机器上。
    • 构件通常在容器中进行管理:按照上面的讨论,构件要屏蔽实现语言、实现方式等很多实现细节,使用一个构件时可以不关心具体实现和位置。这仅是指开发人员不用关心,是不是谁都不用管这些事情,当然不是,如果谁都不去处理不同语言、不同实现方式、不同的物理位置所带来的差异,那用不同语言、不同实现方式实现的、位于不同的物理位置的构件就不可能很好的交互。那具体谁去作这个工作呢br> 通常的做法是设置容器来给构件一个运行环境容器是一种特殊的应用程序,构件在容器中运行和管理。当有客户端要访问某个构件时,实际是向容器发起了一个请求,容器再去判断构件的具体实现语言、实现方式以及构件的具体物理位置,然后帮助请求者与构件进行交互。也就是说,我们所使用的、具备很好特性的构件,实际上是容器和我们用各种语言、方式所编写的程序共同协作的结果。这就要求构件遵循所处的容器的规则,并按照标准的途径向容器发送事件。
    • 构件可以从容器中获得属性或服务:如构件可以使用容器的背景色作为自己的背景色。
    • 构件允许对所支持的接口进行动态发现和调用:客户程序可以在运行状态下确定一个构件支持何种功能,然后调用该功能。

    既然构件具备极好的封装性和可插入性,那么基于构件的系统从可维护性上来讲,就可以达到一种比较理想的状态。如图1-3所示,一个构件化的软件系统在进行维护或升级时,在保持构件接口不变的前提下,可单独对系统中若干个构件进行修改,而不会影响构成系统的其它构件

    在 结构中,由客户端桩 替客户端完成「与服务端程序交互的具体底层通信工作」,客户程序中的远程对象引用实际上是对本地桩的引用;而服务端框架 负责替服务端完成「与客户端交互的具体底层通信工作」。由于客户端桩与服务端框架分别位于客户端与服务端程序的进程内,因此开发人员开发客户端与服务端程序时,只需分别与「本进程内的桩与框架构件」交互,即可实现与远端的交互;而负责底层通信的客户端桩与服务端框架,会在开发过程中自动生成、而非由开发人员编写,从而为开发人员省去底层通信相关的开发工作。

    在 结构的支撑下,客户程序与服务程序按照图中所示的 8 8 8 个步骤完成一服务的调用:

    • ① 客户程序将调用请求发送给客户端桩,对于客户程序来说,桩就是服务程序在客户端的代理
    • ② 客户端桩负责将远程调用请求进行编组,并通过通信总线发送给服务端。
    • ③ 调用请求经通信总线传送到服务端框架。
    • ④ 服务端框架将调用请求解组,并分派给真正的远程对象实现(服务程序)。
    • ⑤ 服务程序完成客户端的调用请求,将结果返回给服务端框架。
    • ⑥ 服务端框架将调用结果编组,并通过通信总线发送给客户端桩。
    • ⑦ 客户端桩将调用结果解组,并返回给客户程序。
    • ⑧ 客户程序得到调用结果。

    结构的支持,使得开发人员从繁杂的底层通信工作中解脱出来,开发人员可以不用编写底层通信代码,即可实现客户端与服务端的远程交互,从而将主要精力集中到业务逻辑的实现上。

    1.4.2 互操作实例

    下面通过一个具体实例来演示互操作的基本原理。该例子实现远程查询通话记录的功能,客户端远程调用分布式对象实现的查询通话记录功能,分布式对象则通过查询数据库完成具体的查询功能。

    该例子程序采用纯Java语言编写,利用 访问关系数据库,并采用远程方法调用 实现客户程序与服务程序之间的交互。客户程序只能通过服务程序间接地访问关系数据库,因而该例子程序属于一种典型的三层设计模型,该例子程序的三层结构与每一层实现基本功能如图1-5所示。

    图 1-7 配置 ODBC 数据源
    为进一步提高程序的数据独立性,还可以利用许多关系DBMS支持的“存储过程”来完成数据的查询与更新操作。数据独立性(逻辑和物理独立性),使得在数据库中表的属性或表之间的关联发生某些变化时,程序员无需对应用程序作任何修改。使用存储过程访问数据库还可带来其他好处,例如提高了SQL语句查询与更新数据库的效率,在 络环境下加强了数据库的安全性等等。在不同的数据库管理系统中,存储过程可能有不同的名字,如保留过程、触发器、查询等。

    下面展示了本例中使用的存储过程(即Microsoft Access中的查询),它根据指定电话用户名字的参数(),查询该用户登记的所有电话的通话记录。本例程序中利用该存储过程实现对数据的查询。

    1.4.2.2 接口定义

    除了数据库中的持久数据外,本例中需要编写的程序代码包括以下几个主要部分:

    • 中间层(服务端程序):
      • 实现分布式对象,完成中间层的核心功能,即具体查询数据库、完成查询通话记录功能;
      • 服务程序:使用 实现分布式对象时,需要开发人员编写一个服务程序,该服务程序完成「真正提供服务的分布式对象」的创建与注册,服务程序中的「真正提供服务的对象实例」通常又称为伺服对象
    • 客户程序:利用服务程序中伺服对象提供的服务,完成通话记录查询的功能。

    在开发服务端程序与客户程序之前,接口是需要首先考虑的问题,因为接口是客户程序与服务端分布式对象之间的约定。在 中分布式对象的接口用Java语言的 定义,并且要求所有分布式对象的远程接口必须继承 接口,还要求其中的每一个方法必须声明抛出 异常,因为 络通信或服务程序等原因均可能导致远程调用失败。

    程序1-1给出了例子程序中通话记录管理器的远程接口定义。定义的接口 约定,服务端的分布式对象提供一个可供远程调用的操作 ,该操作需要一个字符串类型的参数(电话用户的姓名),返回一个 类型的对象(该用户的通话记录)。

    1.4.2.3 服务端程序

    程序1-2定义的类 就是服务端分布式对象的实现该类实现了远程接口 中约定的 方法。为防止多个客户程序并发地调用数据库查询操作,方法 被定义为同步方法

    在 类的实现中,由于 中 结构的支持,因此在实现 方法时,并没有因为该方法是被远程调用的方法、而添加任何代码处理底层通信;在下面的实现代码中,除了方法接口处声明抛出 外,该方法的实现与一个普通Java类中方法的实现没有区别

    // 程序 1-2 CallManager.java // 通话记录管理器(即远程接口 CallManagerInterface 的实现)package Telephone; public class CallManager extends java.rmi.server.UnicastRemoteObject implements CallManagerInterface { 	// 属性定义	protected Database.DatabaseAccess database; 	// 缺省构造方法,必须抛出 RemoteException 异常	public CallManager() throws java.rmi.RemoteException { 		database = new Database.DatabaseAccess(); 	} 	// 根据电话用户名字 subscriber 查询通话记录,实现远程接口指定的方法	public synchronized Database.DatabaseTableModel getCallHistory(String subscriber) throws java.rmi.RemoteException { 		String sql = ""; // SQL 查询语句		Database.DatabaseTableModel table = null; // 返回的二维表模型		System.out.println("Respond to cl
    
                                                            

    声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2022年2月18日
下一篇 2022年2月18日

相关推荐