深蓝海域KMPRO

Web Service Case Study: 认证考试申请服务

2002-08-26 09:22

Web Service Case Study: 认证考试申请服务  



柴晓路 (
fennivel@uddi-china.org)

Chief System Architect

2002年4月10日

本文是Web Service Case Study系列文章的第二篇。在这篇文章中,我将围绕一个认证考试申请系统展开设计和讨论,这个应用与本文的系统不同,主要是面向B2C模式的应用,着眼点在于如何将这个系统的客户端插入到尽可能多的公共平台、桌面系统中去,同时借助这个Case Study,我将着重讲解在Web服务设计的时候,如何有效地使用XML Schema设计系统中使用的XML数据模式。
本文中针对的应用实例是一个认证考试系统,应用背景如下:(以下陈述纯属虚构)

UDDI-China.org是中国的Web Services技术组织,提供Web服务系列技术的技术认证服务,具体负责这个技术认证服务的是UDDI-China.org下的WSTA机构。任何技术人员都可以向WSTA机构提出申请,要求进行某一项Web服务技术(比如XML Schema、SOAP、WSDL、UDDI等)的技术认证,一般流程是要经过申请、修读相应课程、考试这三个主要步骤。WSTA认证考试系统就是为了管理和加速这个流程而开发的一套系统。

在介绍具体的系统流程之前,我们先来看看这个系统的实体关系图:

Figure 1.   认证考试系统实体关系图 


 

结合图1中,我们的系统中,基本上可以有这样三个主要的流程:

注册:申请人需要填写申请表,经过申请审核其资格,通过后准许进入课程修读以及考试流程;

课程修读:通过了申请之后,系统将为这个申请人自动安排一个课程的修读日程,并安排指定授课老师;

考试:当申请人经过课程的修读(当然也可以不读书直接考试),可以申请参加考试,系统将自动为其安排一个考试日程,当申请人完成考试后,将得到相应的成绩单以及认证证书(当然要是通过的)。

设计人员希望这个系统的使用者不但能够通过UDDI-China.org的Web Page来使用认证考试系统,同时设计人员还希望能让各种桌面工具能够直接与UDDI-China.org的认证考试系统集成,比如用户在使用个人事务计划软件时,就能够将申请、听课和考试等事务纳入系统的安排,涉及的事务安排可以通过个人事务计划软件与UDDI-China.org的认证考试系统的交互来自动完成。交互的界面被设计为使用Web服务调用接口,而Web服务接口中输入/输出的数据应当是XML格式的,抛开Web服务调用接口先不谈,我们先来看看系统接口中需要使用的XML数据模型。

经过系统分析,设计人员认为以下实体是需要使用XML来描述的:

Application,在这个XML描述实体中,将涉及图1中的Applicant和Application;

CourseSession,在这个XML描述实体中,将涉及图1中的Applicant、Employee、CourseSession和Course;

ExamSession,在这个XML描述实体中,将涉及图1中的Applicant、ExamSession、Exam和Test。

下面,我们分别给出这三个XML实例文档的模式。

XML Schema建模

Application

首先,我们给出Application文档的XML Schema定义及其模式图示,随后我们再一一详细解释模式的细节。

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="
http://www.w3.org/2001/XMLSchema"
       elementFormDefault="qualified" attributeFormDefault="unqualified">
  <xs:element name="Application" type="applicationType">
    <xs:annotation>
      <xs:documentation>Application的模式定义</xs:documentation>
    </xs:annotation>
  </xs:element>
  <xs:complexType name="applicationType">
    <xs:annotation>
      <xs:documentation>Application类型定义</xs:documentation>
    </xs:annotation>
    <xs:sequence>
      <xs:element name="person" type="personType"/>
      <xs:element name="company" type="xs:string"/>
      <xs:element name="experience" type="xs:string"/>
      <xs:element name="reference" type="xs:string" minOccurs="0" maxOccurs="3"/>
      <xs:element name="certificationID" type="xs:long"/>
      <xs:element name="applicationDate" type="xs:date"/>
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="personType">
    <xs:annotation>
      <xs:documentation>个人信息类型定义</xs:documentation>
    </xs:annotation>
    <xs:sequence>
      <xs:element name="personID" type="xs:long"/>
      <xs:element name="name">
        <xs:complexType>
          <xs:sequence>
            <xs:element name="surname" type="xs:string"/>
            <xs:element name="givenName" type="xs:string"/>
          </xs:sequence>
        </xs:complexType>
      </xs:element>
      <xs:element name="contact" type="contactType" maxOccurs="unbounded"/>
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="contactType">
    <xs:annotation>
      <xs:documentation>联系方法类型定义</xs:documentation>
    </xs:annotation>
    <xs:choice>
      <xs:element name="email"/>
      <xs:element name="phone"/>
      <xs:group ref="mailAddress"/>
    </xs:choice>
  </xs:complexType>
  <xs:group name="mailAddress">
    <xs:sequence>
      <xs:element name="streetAddress" type="xs:string"/>
      <xs:element name="postCode" type="xs:string"/>
    </xs:sequence>
  </xs:group>
</xs:schema>

上面的代码给出了Application的XML Schema文档,其中定义了一个Application元素,这个元素是Application数据文档的根元素。Application元素使用了applicationType这个复合类型作为它的类型定义。而applicationType类型定义引用了personType这个类型定义作为个人信息的描述,personType类型定义中使用了contactType类型定义来描述个人的联系方式,而contactType类型定义还使用了mailAddress这个组定义,以支持choice的定义方式。

在详细介绍这个层次结构之前,我们可以先来看一看图2的模式图示。

Figure 2.   Application模式图示 


 

applicationType复合类型用于描述一个申请表,applicationType复合类型定义包含了6个子元素:person、company、experience、reference、certificationID、applicationDate,分别表示个人信息、所属公司、工作经验、参考技能认证、认证考试ID、申请日期。其中person的类型是复合类型personType,而其他5个元素都是简单类型。company、experience、reference的类型都是字符串xs:string,certificationID的类型是xs:long,而applicationDate的类型是xs:date。其中除reference的出现次数可以是0到3次以外,其他的元素都是出现且仅出现1次。

person子元素应用了personType复合类型,personType复合类型定义包含了3个子元素:personID、name和contact,分别表示个人ID、姓名和联系方法。personID是一个简单类型元素,类型为xs:long。name是一个复合结构,包含了两个子元素surname和givenName,共同描述了人的姓名。

而contact子元素则是应用了contactType复合类型定义,contactType是一个选择类型,应用contactType类型的元素可以选择是包含一个email子元素、或是包含一个phone子元素,或是包含一个mailAddress子元素,mailAddress使用了在后面定义的元素组定义mailAddress。

为了使得对contact元素的定义理解地更为具体一些,我们下面给出一些contact元素的实例表示的例子,具体的,包含在person元素内。

<person>
  <personID>20302290</personID>
  <name>
    <surname>Joe</surname>
    <givenName>Huang</givenName>
  </name>
  <contact><email>Joe.Huang@hotmail.com</email></contact>
  <contact><email>Joe.Huang@yahoo.com</email></contact>
  <contact>
    <mailAddress>
      <streetAddress>No.2000, Huangxing Road, Shanghai</streetAddress>
      <postCode>200433</postCode>
    </mailAddress>
  </contact>
</person>

上面的代码给出了一个person的实例文档,其中这个个人信息包含了三个联络方式,两个是email地址,一个是寄信地址,此人没有留下联系电话。

最后,我们给出Application模式的一个完整的实例文档。

<?xml version="1.0" encoding="UTF-8"?>
<Application>
  <person>
    <personID>20302290</personID>
    <name>
      <surname>Joe</surname>
      <givenName>Huang</givenName>
    </name>
    <contact><email>Joe.Huang@hotmail.com</email></contact>
    <contact><email>Joe.Huang@yahoo.com</email></contact>
    <contact>
      <mailAddress>
        <streetAddress>No.2000, Huangxing Road, Shanghai</streetAddress>
        <postCode>200433</postCode>
      </mailAddress>
    </contact>
  </person>
  <company>Innoteck Company</company>
  <experience>System Architect of Innoteck</experience>
  <certificationID>X00910</certificationID>
  <applicationDate>2002-2-18</applicationDate>
</Application>

CourseSession

同样,我们先给出CourseSession的XML模式文档,CourseSession用于描述一门课程的某一个学期的安排。

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="
http://www.w3.org/2001/XMLSchema"
       elementFormDefault="qualified" attributeFormDefault="unqualified">
  <xs:element name="CourseSession" type="CourseSessionType">
    <xs:annotation>
      <xs:documentation>CourseSession Schema Definition</xs:documentation>
    </xs:annotation>
  </xs:element>
  <xs:complexType name="CourseSessionType">
    <xs:sequence>
      <xs:element name="Course" type="CourseType"/>
      <xs:element name="Session" type="SessionType"/>
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="SessionType">
    <xs:sequence>
      <xs:element name="CourseSessionID" type="xs:long"/>
      <xs:element name="CourseLocation" type="xs:string"/>
      <xs:element name="CourseDate" type="CourseDateListType"/>
      <xs:element name="Teacher" type="EmployeeType"/>
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="CourseType">
    <xs:sequence>
      <xs:element name="courseID" type="xs:long"/>
      <xs:element name="certificationID" type="xs:long"/>
    </xs:sequence>
  </xs:complexType>
  <xs:simpleType name="CourseDateListType">
    <xs:list itemType="xs:date"/>
  </xs:simpleType>
  <xs:complexType name="EmployeeType">
    <xs:complexContent>
      <xs:extension base="personType">
        <xs:sequence>
          <xs:element name="jobTitle"/>
          <xs:element name="department"/>
          <xs:element name="roomNumber"/>
        </xs:sequence>
      </xs:extension>
    </xs:complexContent>
  </xs:complexType>
  <xs:complexType name="personType">
    <xs:sequence>
      <xs:element name="personID" type="xs:long"/>
      <xs:element name="name">
        <xs:complexType>
          <xs:sequence>
            <xs:element name="surname" type="xs:string"/>
            <xs:element name="givenName" type="xs:string"/>
          </xs:sequence>
        </xs:complexType>
      </xs:element>
      <xs:element name="contact" type="contactType" maxOccurs="unbounded"/>
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="contactType">
    <xs:choice>
      <xs:element name="email"/>
      <xs:element name="phone"/>
      <xs:group ref="mailAddress"/>
    </xs:choice>
  </xs:complexType>
  <xs:group name="mailAddress">
    <xs:sequence>
      <xs:element name="streetAddress" type="xs:string"/>
      <xs:element name="postCode" type="xs:string"/>
    </xs:sequence>
  </xs:group>
</xs:schema>

其中复合类型personType、contactType以及元素组mailAddress的定义与前面代码中的Application模式文档中的定义是一样的,在这个文档中,我们给出这部分定义是为了EmployeeType的定义需要,在这里,EmployeeType类型定义扩展继承了personType的类型定义。

其次,CourseSession模式文档的其他部分分别定义了CourseSessionType、CourseType和SessionType三个复合类型以及一个列表类型CourseDateListType。在详细介绍这些类型定义之前,我们先给出CourseSession的模式图示,以加深形象认识。

Figure 3.   CourseSession模式图示 


 

下面我们结合图3的模式图示来讲解一下CourseSession模式定义。

课程学期安排描述CourseSession由两部分组成(定义在CourseSessionType中):Course课程和Session学期安排。其中Course子元素应用了CourseType复合类型,该复合类型包含了两个子元素CourseID和certificationID,分别表示这个课程的ID标识以及这个课程对应的认证考试ID标识。而Session子元素则是应用了SessionType复合类型,该复合类型包含四个子元素:CourseSessionID、CourseLocation、CourseDate和Teacher。CourseSessionID、CourseLocation是两个简单类型的子元素,分别表示课程学期安排的标识ID以及课程的授课地点。CourseDate是一个列表类型的元素,它的值是日期列表,表示课程的授课时间。而Teacher子元素应用了EmployeeType复合类型,表示该课程这个学期的授课老师。

其中EmployeeType复合类型定义扩展继承了personType的类型定义。关于扩展继承的特性,在这里暂时先不详细介绍,我将在后面的章节中给出描述的细节。

最后,按照前面的惯例,我们给出CourseSession模式的一个实例文档作为本节的结尾。

<?xml version="1.0" encoding="UTF-8"?>
<CourseSession>
  <Course>
    <CourseID>X0091001</CourseID>
    <certificationID>X00910</certificationID>
  </Course>
  <Session>
    <CourseSessionID>X009100120020220</CourseSessionID>
    <CourseLocation>Shanghai Education Center</CourseLocation>
    <CourseDate>2002-2-20 2002-2-22 2002-2-26</CourseDate>
    <Teacher>
      <personID>10307827</personID>
      <name>
        <surname>Mike</surname>
        <givenName>Liu</givenName>
      </name>
      <contact><email>Mike.Liu@uddi-china.org</email></contact>
      <contact><phone>13717652090</phone></contact>
      <contact>
        <mailAddress>
          <streetAddress>No.1 UDDI-China Way, Shanghai</streetAddress>
          <postCode>200400</postCode>
        </mailAddress>
      </contact>
    </Teacher>
  </Session>
</CourseSession>

ExamSession

同样,我们先给出ExamSession的XML模式文档,ExamSession用于描述某一门认证考试的某一场考试的安排。

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="
http://www.w3.org/2001/XMLSchema"
       elementFormDefault="qualified" attributeFormDefault="unqualified">
  <xs:element name="ExamSession" type="ExamSessionType">
    <xs:annotation>
      <xs:documentation>ExamSession Schema Definition</xs:documentation>
    </xs:annotation>
  </xs:element>
  <xs:complexType name="ExamSessionType">
    <xs:sequence>
      <xs:element name="Exam" type="ExamType"/>
      <xs:element name="Session" type="eSessionType"/>
      <xs:element name="finished" type="xs:boolean"/>
      <xs:element name="ScoreReport" type="ScoreReportType" minOccurs="0"/>
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="ExamType">
    <xs:sequence>
      <xs:element name="examID" type="xs:long"/>
      <xs:element name="certificationID" type="xs:long"/>
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="eSessionType">
    <xs:sequence>
      <xs:element name="examSessionID" type="xs:long"/>
      <xs:element name="examLocation" type="xs:string"/>
      <xs:element name="examDate" type="xs:date"/>
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="ScoreReportType">
    <xs:sequence>
      <xs:element name="personID" type="xs:long"/>
      <xs:element name="score" type="xs:integer"/>
    </xs:sequence>
  </xs:complexType>
</xs:schema>

这个模式文档相对于Application模式文档和CourseSession模式文档来说比较简单。在这个模式文档中,主要为定义一个XML文档元素ExamSession,ExamSession元素应用了ExamSessionType复合类型。ExamSessionType复合类型定义包含了三个四元素Exam、Session、finished和ScoreReport,分别表示认证考试、认证考试的某一场考试的安排、考试是否完成以及成绩单。这个XML文档用于在客户端和服务器端互相交换ExamSession,比如用户期望申请某一项认证考试,当然会希望获得所有的相关ExamSession信息。当某一个ExamSession结束后,这个XML文档也用于传输用户的成绩。

图4给出了这个XML模式的模式图示,通过这个模式图示,大家应该能够更好地理解这个模式的结构。

Figure 4.   ExamSession模式图示 


 

最后我们按照这个模式文档,给出它的一个实例文档,作为本节的结束。

<?xml version="1.0" encoding="UTF-8"?>
<ExamSession>
  <Exam>
    <examID>EX00910</examID>
    <certificationID>X00910</certificationID>
  </Exam>
  <Session>
    <examSessionID>EX0091020020309</examSessionID>
    <examLocation>Shanghai Education Center</examLocation>
    <examDate>2002-3-9</examDate>
  </Session>
  <finished>true</finished>
  <ScoreReport>
    <personID>20302290</personID>
    <score>92</score>
  </ScoreReport>
</ExamSession>

应用模式演示

在这里,我们将外部的应用假设也加入到整个应用模式中来,参照下图,其中National Education Information Portal是一个国家范围的教育信息门户网站,而Global IT Education Web Service则是一个全球IT教育机构提供的一个在线Web服务。它们都以这个认证考试申请系统的Web服务客户端应用的角色出现在应用模式中。(以下的应用模式发展流程完全属于应用假设,其中的所有实体和细节纯属虚构)

Figure 5.   应用模式演示 


 

如图所示,Web服务认证机构WSTA开始向公众提供Web服务技术认证服务,一开始这个服务仅在机构内部工作,工作人员通过手工或Email收取报名表格,然后在自己的桌面应用中为客户完成相关的注册,上课和考试等申请流程,按照这种方式,整个机构的运行效率不高,所有的流程瓶颈集中在机构内部的桌面应用上。随着申请认证考试的学员不断增多,WSTA不得不使用其提供认证的技术:Web服务技术来改造他的应用。完成认证考试各项申请的逻辑被包装成EJB Web Service,并部署在机构内部的BEA Weblogic Application Server上,而桌面应用也被升级以支持对Web服务调用(也就是成为了一个Web Service Client),为了使得这个认证申请Web服务(WSTK Web Service)能够被更多的人通过各种平台进入并使用,这个Web服务被注册进了Public UDDI Registry,并发布了它的WSDL描述文档。同时,WSTA也积极与公共教育平台进行接触并尝试合作可能。经过一番接触,国家教育信息门户(National Educastion Information Portal, NEIP)同意与WSTA进行系统对接,以实现在NEIP平台上直接对WSTA提供的Web服务技术认证考试处理申请流程。NEIP采用的是Microsoft .NET的平台,因此在这里实施了J2EE和.NET平台的连接集成。同时由于将自身注册入了Public UDDI Registry,WSTA的认证考试申请服务有机会被更多的外部平台集成使用。如图中的Global IT Education Web Service就是一例,Global IT Education通过对Public UDDI Registry的搜索,搜索全球提供IT认证的机构,WSTK的Web服务是处于搜索结果集中的,Global IT Education通过处理搜索到的WSDL文档,完成了对WSTK的Web服务的绑定,实现了Global IT Education Web Service与WSTK Web Service的连接。

下面,我们按照图中的序号标明的顺序,逐一讲解在这个Web服务的应用场景下,各个组件是如何协同实施和运作的:

用户可以通过NEIP的Web界面申请Web服务技术认证的注册、课程和考试;

NEIP的Web站点把请求通过Internet发送给WSTK的认证管理Web服务;

WSTK的认证申请管理Web服务通过与机构数据库的交互,完成申请事务,并响应NEIP的Web站点,并最终将响应返回终端用户;

WSTK认证服务的技术信息(比如WSDL文档)被注册入了Public UDDI Registry供公共查询;

Global IT Education的在线服务通过搜索Public UDDI Registry,寻找到了WSTK认证申请服务;

Global IT Education获得WSTK认证申请服务的技术信息,实现动态绑定;

Global IT Education建立与WSTK认证申请服务的应用集成;

任何使用Global IT Education的应用(包括各种应用、Web站点、Web服务)都可以通过Global IT Education的Web服务来使用WSTK认证申请服务;
WSTK内部的桌面应用同样是使用Web服务界面绑定的技术来调用WSTK认证申请服务的。

服务的可用性和连接的持久性

既然这个认证考试申请服务是面向广大的个人用户的,用户不但可以通过WSTK机构进行申请,同时也可以通过任何的集成了WSTK认证考试申请服务的应用、平台、网站等使用这个认证考试申请服务。对于WSTK而言,使用的用户越多,就越证明WSTK认证考试申请服务的成功,而使用的用户越多,一般而言,也意味着与WSTK认证考试申请服务建立Web服务连接的应用程序、平台或网站也越多。然后,任何事情都有其正反两方面的影响,如果使用的用户非常多,接入的平台、应用的数量也非常多的话,WSTK认证考试申请服务的可用性,以及连接的持久性就成为了一个非常非常关键的问题。

关于传统软件领域,甚至是硬件领域中涉及的稳定性、可用性和持久性方面,我就不再在这里探讨了,这不属于我们正面对的基于Internet的分布式应用环境的这个分布式应用集成。那么我们需要面对的是什么呢?

如果WSTK认证考试申请服务这个Web Service所在的系统发生崩溃或者因为系统维护的原因,WSTK不得不把这个服务临时迁移到备份服务器上,服务所在服务器的IP地址发生了变化,甚至,服务入口的URL也可能发生了变化。此时,现存的所有连接将不再有效(地址和入口都变了,自然不会持续有效),那么快速地恢复连接是我们需要处理的问题。

回顾一下,以前我们在做EAI时候的方法,对每个相关模块/系统的开发人员、维护人员发出通知,要求他们更改相应的代码,这在企业内部情况尚好,我们还是能够在一定时间内通知到每个人,然后各个模块依照人员的技术能力和工作时间的多少,一一完成了连接的恢复,不过万一负责某个模块的技术人员出差或其他一些原因无法更新相应的代码,那么这个模块将有一段时间无法使用。现在将这一情况从企业内拓展到了企业间、机构与个人之间后,情况似乎变得更为复杂,相同的意外情况往往导致非常恶劣的后果。

首先,我们是否还能通知到每个与WSTK服务相连接的企业或机构,其中部分按照合约方式建立连接的也许可以,然而由于是位于不同企业,之间的协同存在问题。同时还有一大部分是通过查询Public UDDI Registry找到WSTK的服务从而和WSTK服务建立连接的应用,这些应用的维护者,我们根本无法通过一般的途径找到他们,如果仍然只能使用人与人的交流方式,那么这些连接将在一段时间内中断,如果服务被永久性地迁移了,那么这些好不容易发展起来的连接将从此中止。

其次,WSTK服务是一个最终服务,中间会有很多门户网站、机构网站以WSTK服务的代理的形式直接向最终用户提供服务。如果WSTK服务的质量出现问题,这些门户网站、机构网站可能因他们自身网站、服务的声誉问题,而考虑是否以后还要在他们的网站、服务中提供对WSTK认证考试申请的服务。因为对于最终用户而言,他们使用的就是这些网站、机构所提供的服务,他们并不知道最终WSTK认证考试申请服务才是最终的服务提供者,因此如果WSTK认证考试申请服务不工作,他们就是认为是这些网站、机构的服务不工作了。

再次,还有相当一部分是直接被集成到终端用户的桌面应用的,对于这种情况,WSTK更是没有办法通过传统的方式重建连接了……

我们面临的问题是很严峻,不过由于我们采用的是Web服务架构,利用的是UDDI作为我们的服务发现机制,因此这种服务连接恢复的问题,我们可以通过UDDI所提供的机制来尝试解决。

我们知道,WSTK一开始就把WSTK认证申请服务注册到了UDDI注册中心,具体的说,是在UDDI注册中心中注册了一个businessService(对应于这个服务),这个businessService中包含了一个bindingTemplate用于描述这个服务的技术调用规范,其中包含了这个Web服务的访问入口以及如何访问这个Web服务的WSDL文档等等。对于搜索UDDI Registry的企业/机构而言,他们需要得到的就是bindingTemplate信息,从UDDI注册中心中获得的bindingTemplate信息集中的数据表示了一个指定的远端Web服务的调用规范实例。这些企业/机构的应用程序应当缓存该信息并且使用这个调用规范通过该WSTK服务注册的地址来访问这个WSTK Web Service。

当使用从UDDI注册中心中获得并缓存下来的信息(调用入口等)进行调用发生失败时,正确的做法是去查询当初获得该数据的UDDI注册中心并获取与其对应的更新了的bindingTemplate信息。也就是说,当一个服务因为维护或灾难恢复发生迁移时,一旦迁移完成这个服务应当主动去更新在UDDI Registry中相应的bindingTemplate记录。对应于前面的WSTK服务的情形,WSTK服务应当去更新其对应的bindingTemplate中的访问入口地址URL等。

在使用Web服务中,使用这样的调用模式,那么使用UDDI操作入口站点(Operator Site)的商业实体就得以在不加重通信与协调开销的情况下自动完成与大量合作伙伴的服务恢复。这一过程的详细程序式描述如下:

服务提供者使用save_xx在UDDI注册中心中注册了Web服务S;

调用者使用find_xx查询UDDI注册中心,获得所需的服务S的概要信息;

调用者使用get_xx再一次查询UDDI注册中心,获得所需服务S的详细信息;

调用者缓存服务S的bindingTemplate信息,通过服务绑定,实施对服务S的调用;

服务S由于某种原因出现问题,无法继续提供服务;

服务提供者在新的位置重新部署了服务S,同时更新了UDDI注册中心的关于Web服务S的技术描述;

调用者使用缓存的服务S的bindingTemplate信息再一次进行调用,调用失败;(服务S的部署位置已经更改)

调用者使用缓存的bindingTemplate的bindingKey键值查询UDDI注册中心,获得服务S的更新后的bindingTemplate信息。

调用者缓存服务S的新的bindingTemplate信息,通过服务绑定,重新实施对服务S的调用。

服务的延伸

由于WSTK认证考试申请服务已经以Web服务的方式架构起来了,在成功应用一定时间之后,这个服务架构将成为一个解决方案在一定范围内实施推广,一个快速有效的办法是将这个认证考试申请服务升级为一个ASP服务,供各种提供认证考试的机构通过Internet租用。这是一个有效利用资源和盈利的渠道。不过此时我们面临的情况将更加复杂。由于是ASP服务,一般来说,在ASP服务中,租用者并不是ASP服务的所有者,他们各自的服务入口可能是彼此不同的,但不排除彼此相同的实现可能(比如通过提供不同的用户名/密码,但入口是一个),同时这些入口调用信息并不是由租用者来管理的,事实上,当ASP服务的提供者更改入口地址也是可能发生的异常情况。此时仍然要求由服务提供者去更新bindingTemplate信息以满足服务迁移的平滑性变得不再实际了。

那么,马上可以想到的,就是所有与这个ASP服务相关的bindingTemplate都由ASP服务的提供者来管理。不过,这仍然不切实际,因为如此一来,就违背UDDI Registry搜索的初衷了,首先搜索者是要搜索商业实体businessEntity,如果不同的机构的businessService都被保存在ASP服务提供者的businessEntity下,显然与用户的搜索方式相悖,同时对于businessService的描述信息,那些提供认证考试的机构都期望自己来维护,显然这不是一个正确的合适的解决方案。UDDI在bindingTemplate机制里面提供了一个重定向的方法来试图解决这个问题,关于这个方法我将在本系列的下一篇文章中结合下一个实例给出。

大家对于这两个问题的任何建议以及大家想到的其他可能的问题,都欢迎到论坛来提出意见或给出评论。

参考资料

作者简介

 柴晓路: 上海得易电子商务技术有限公司(DealEasy)首席系统架构师、XML Web Sevices技术顾问,UDDI-China.org创始人,UDDI Advisory Group成员,现在是WS-I.org 的 Working Group 的成员,参与 Profile 和 Usage Scenario的工作。 IBM developerWorks专栏作家。2000年获复旦大学计算机科学硕士学位,曾在国际计算机科学学术会议(ICSC)、亚太区XML技术研讨会(XML Asia/Pacific'99)、中国XML技术研讨会(北京)、计算机科学期刊等各类国际、国内重要会议与期刊上发表论文多篇。专长于Web Services技术架构、基于XML的系统集成和数据交换应用及方法,同时对数据库、面向对象技术及CSCW等技术比较擅长。

 

相关推荐