美文网首页
Web Service系列文章之一:概念梳理

Web Service系列文章之一:概念梳理

作者: 小胖0_0 | 来源:发表于2018-05-06 18:51 被阅读249次

要想系统的学习一门技必,须要先清楚这门技术的“前世今生”。这项技术是如何出现的?为什么会出现这项技术?一项新技术的出现必然是为了解决某个痛点或者说满足某个需求,那么这个痛点或者这个需求是什么?那么我们才能知道这项技术的优势是什么,什么时候适合使用这项技术,当前有没有什么更好的替代方式。

了解技术背景首先首先绕不开的就是一些相关的概念。本文涉及的概念较多,需要仔细阅读,思考,有些概念可能讲得并不是很清楚,需要自行再补充了解一些知识。

一、SOA

Service Oriented Ambiguity 中文一般理解为:面向服务架构,简称SOA。

SOA 的提出是在企业计算领域,就是要将紧耦合的系统,划分为面向业务的、粗粒度、松耦合、无状态的服务。服务发布出来供其他服务调用,一组互相依赖的服务就构成了SOA架构下的系统。

既然说是一种架构的话,所以一般认为SOA是包含了运行环境,编程模型,架构风格和相关方法论等在内的一整套新的分布式软件系统构造方法和环境,涵盖服务的整个生命周期。

SOA 本质上是服务的集合。

服务间彼此通信,这种通信可能是简单的数据传送,也可能是两个或更多的服务协调进行某些活动。既然服务之间需要进行通讯,那么服务间就需要某些方法进行连接。

所谓服务就是精确定义、封装完善、独立于其他服务所处环境和状态的函数或功能

我们可以看出 SOA 的几个关键特征:粗粒度、松耦合、互相通讯、通讯接口简单而精确、不涉及底层编程接口和通讯模型

对于理解 Web Service 来说,我们并不需要过多纠结 SOA 到底是个怎样的构架,只需要知道它是一种软件构架思想,满足它的定义和规范的软件系统都可以认为其是 SOA 构架。而 Web Service 则是实现 SOA 构架最合适的技术之一。

二、Web Service

在解释 Web Service 之前,先抛出一个问题:有没有一种办法可以实现跨应用程序进行通信和跨平台进行通信呢?

跨应用程序,主要是指我家开发的系统和别人家开发的系统之间是否可以通信。

跨平台,主要是指我家用 Java 开发的系统和别人家用 .NET 开发的系统是否可以通信。

像这样的需求是非常多的,尤其是我们做企业信息化服务的,几乎每个项目都会涉及到多个系统的对接,而这些系统的开发方式、实现方式各种各样,无法统一。

举一个最简单的例子:获取天气信息。这里以腾讯QQ上面自带的天气功能为例。

腾讯要想获得实时的天气信息怎么办呢?有一种办法,那就是腾讯公司放个卫星上天,并且在公司中成立一个气象部门,天天关注于天气,然后每时每刻更新腾讯QQ上的这个天气预报信息。这显然不是一种明智的做法,只是想获取一下天气信息,居然要如此高的成本。

简单的做法是让中国气象台提供实时的天气信息,然后,通过提供接口的方式给腾讯调用。那么这就遇到上面所说的问题,如何跨应用与跨平台调用接口。

这个时候我们都会想到 HTTP 协议,主流的编程语言都可以实现基于 HTTP 协议的应用开发。让中国气象台写个基于 HTTP 协议的天气接口给腾讯调用就可以了。当然,这是完全可以的。不过,在 HTTP 协议被提出并广泛应用了这么多年之后,又出现了 Web Service,必然是有其原因的。

其实,这里拿 Web Service 与 HTTP 进行比较并不十分合适。因为 HTTP 是互联网上应用最为广泛的一种网络协议,几乎所有的网络间通讯都是基于 HTTP 协议的。而 Web Service 是一种部署在 Web 服务器上的应用程序组件,Web Service 数据的传输同样需要借助 HTTP 协议,因此可以将 Web Service 理解为一个基于 HTTP 协议开发的上层应用程序。

更详细的定义:

Web service 是一个平台独立的,低耦合的,自包含的、基于可编程的 Web 的应用程序,可使用开放的 XML(标准通用标记语言下的一个子集)标准来描述、发布、发现、协调和配置这些应用程序,用于开发分布式的互操作的应用程序。

三、SOA 与 Web Service

早在1996年Gartner就前瞻性地提出了面向服务架构的思想(SOA),那时候 Web Service 还不知为何物,SOA 还只是束之高阁的理论概念。直到2000年以后,W3C才成立了相关的委员会,开始讨论 Web Service 的相关标准,各大厂商一边积极参与标准制定,一边推出了一系列实实在在的产品。新的技术和新的产品出现,SOA 找到了可以依托的凭借。随着 Web Service 技术的推出和应用,SOA 的思想被一个个效益显著的信息系统建设项目不断的示范,才逐渐成为现今的热门话题。

因为现在几乎所有的 SOA 应用场合都是和 Web Service 绑定的(即以 Web Service 技术为手段实现 SOA 软件系统构架),所以不免有时候这会将两个概念混用。不可否认的是 Web Service 是现在最适合实现 SOA 的技术,SOA 的走红在很大程度上归功于 Web Service 标准的成熟和应用的普及。因为现在大家基本上认同 Web Service 技术在几方面体现了 SOA 的需要:

  1. 基于标准访问的独立功能实体满足了松耦合要求:在 Web Service 中所有的访问都通过 SOAP 访问进行,用 WSDL 定义的接口封装,通过 UDDI 进行目录查找(SOAP、WSDL 和 UDDI 的概念后面会讲),可以动态改变一个服务的提供方而无需影响客户端的配置,外界客户端是根本不关心访问服务器端的实现。

  2. 适合大数据量低频率访问符合服务大颗粒度功能:基于性能和效率平衡的要求,SOA 的服务提供的是大颗粒度的应用功能,而且跨系统边界的访问频率也不会象程序间函数调用那么频繁。通过使用 WSDL 和基于文本 (Literal) 的 SOAP 请求,可以实现能一次性接收处理大量数据。

  3. 基于标准的文本消息传递为异构系统提供通讯机制:Web Service 所有的通讯是通过 SOAP 进行的,而 SOAP 是基于 XML 的,XML 是结构化的文本消息。文本消息具有易读易写、简单有效、跨平台等特点,从最早的 EDI (Electronic Data Interchange 电子数据交换)开始,文本消息也许是异构系统间通讯最好的消息格式,适用于 SOA 强调的服务对异构后天宿主系统的透明性。

综合上述观点,Web Service 不愧为当前 SOA 的最好选择。然而,就SOA思想本身而言,并不一定要局限于 Web Service 方式的实现。更应该看到的是 SOA 本身强调的是实现业务逻辑的敏捷性要求,是从业务应用角度对信息系统实现和应用的抽象。随着人们认识的提高,还会有新技术不断的发明出来,更好的来满足这个要求。例如现在比 Web Service 更加流行的基于 Restful 和 Json 实现方式。

用一句话总结 SOA 与 Web Service 之间的关系

SOA 不是 Web Service,Web Service 是目前最适合实现SOA的技术

四、利用 Web Service 技术实现的多系统对接实例

上面我们介绍了 SOA 和 Web Service 的一些相关概念以及二者之间的关系。现在我用一个实际项目上的情况来对照上面的概念具体描述一下 Web Service 在多个系统对接是的工作方式。如下是一个简化版的丽珠集团部分系统的服务通信结构图:

image

丽珠集团在使用中的有电子商务系统EBS、汉得医药质量管理系统HGXP、主数据管理系统MDM、企业服务总线ESB、供应商管理系统SRM、丽珠自研的订单管理系统EOS等等多个系统。

这些系统各有个的主要功能,但是各个系统之间的数据是需要流转的,那么这就要求各个系统之间都能够互相通信。例如HGXP的资质校验服务需要提供给EBS和EOS调用,那么HGXP与BES、EOS之间就必须能够通信。

这些系统各自都是能够独立工作的,同时它们各自还对外提供一些服务,这些服务的集合,我们可以将其看作为一个 SOA 构架的系统。

但是这些系统各自的实现方式都不一样,作为 HGXP 系统的开发者,我只知道 HGXP 是一个 Java 语言开发的 BS 构架的系统,我并不知道 EBS、MDM、SRM等其他系统是如何开发的,但是我们之间又需要互相通讯,共享数据或者互相调用服务,这个时候 Web Service 就体现出其优势了。

如上面所说,Web Service 是一个标准访问的功能,作为服务的调用方,不需要关心服务提供方是如何实现的,我只需要一个调用接口和标准访问格式,即可调用服务。同时基于标准文本消息的方式在多种系统之间传输数据也更加直观透明,便于理解、调试和集成。

丽珠集团信息化由于设涉及系统种类繁多,各个系统之间接口调用繁杂,因此还单独引进了 ESB(企业服务总线),将所有外围系统提供的服务和接口统统在 ESB 系统注册,由 ESB 系统分发各个系统提供的数据和服务。

例如,HGXP 系统提供了资质校验功能,那么将这个服务在 ESB 中注册,然后 EOS 和 ESB 需要调用资质校验功能的时候直接去找 ESB 系统对接即可,避免服务提供方和调用方直接接触,可以实现服务之间的再次解耦。如下图:

image

两个调用方的时候还不能凸显出 ESB 解耦的作用,假设有10个调用方,这个时候 ESB 的作用就更加明显了:当资质校验服务需要切换提供方或者因故宕机需要切换服务器的时候,只需要 ESB 切换一个服务商即可,而前一种方式需要各个调用方自行切换服务商,成本会大大增加。

如上这些系统之间所有的通讯和数据流转用都是用的 Web Service 方式。Web Service 还有一个好处,就是经过多年的标准化和市场化,几乎所有的主流信息系统都是支持 Web Service 服务接收和开发的,虽然也有不少别的技术能够实现夸系统跨平台的数据通讯,但是市场支持率并不一定有 Web Service 高,开发成本方面可能会更高。另外,作为企业级应用,最看重的并不是技术的先进性,而是技术的稳定性和规范性,在这点上 Web Service 还是有很强的优势的。

五、SOAP

Simple Object Access Protocol,中文为简单对象访问协议,简称 SOAP。

SOAP 是基于 XML 在分散或分布式的环境中交换信息的简单的协议。允许服务提供者和服务客户经过防火墙在 INTERNET 进行通讯交互。SOAP 的设计是为了在一个松散的、分布的环境中使用 XML 对等地交换结构化的和类型化的信息提供了一个简单且轻量级的机制。

XML 是可扩展标记语言。如下:

<bookstore>
    <book category="COOKING">
        <title lang="en">Everyday Italian</title> 
        <author>Giada De Laurentiis</author> 
        <year>2005</year> 
        <price>30.00</price> 
    </book>
</bookstore>

SOAP 消息的基本结构。如下:

<?xml version="1.0"?>
<soap:Envelope xmlns:soap="http://www.w3.org/2001/12/soap-envelope"
soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding">

  <soap:Header>
      ...
      ...
  </soap:Header>

  <soap:Body>
      ...
      ...
      <soap:Fault>
        ...
        ...
      </soap:Fault>
  </soap:Body>

</soap:Envelope>

当 SOAP 消息真正需要在网络上实际传输的时候,SOAP 消息能够与不同的底层传输协议进行绑定,同时,SOAP 消息可以在很多种消息传输模式中使用。包括超文本传输协议(HTTP),简单邮件传输协议(SMTP),多用途网际邮件扩充协议(MIME)。它还支持从消息系统到远程过程调用协议(RPC)等大量的应用程序。

当然,最多的情况还是绑定在 HTTP 协议上面传输。这就导致大多数人认为 SOAP 就是 HTTP + XML,或者认为 SOAP 是 HTTP Post请求的一个专用版本,遵循一种特殊的 XML 消息格式。虽然,我们看到的大多情况确实如此,但这并不是 SOAP 本质与全部。

六、WSDL

Web Services Description Language,网络服务描述语言,简称 WSDL。它是一门基于 XML 的语言,用于描述 Web Services 以及如何对它们进行访问。如下如图是丽珠 HGXP系统中 Web Service 地址和 WSDL 文档地址:

image

点击 WSDL 后面的连接地址即可查看 WSDL 文档。

WSDL 文档主要使用以下几个元素来描述某个 web service :

<portType> web service 执行的操作。

<message> web service 使用的消息。

<types> web service 使用的数据类型。

<binding> web service 使用的通信协议。

如下代码是 HAP 框架自带的 Demo sayHello接口的 WSDL 文档:

<?xml version='1.0' encoding='UTF-8'?><wsdl:definitions xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:tns="http://ws.demo.hap.hand.com/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:ns1="http://schemas.xmlsoap.org/soap/http" name="HelloGT" targetNamespace="http://ws.demo.hap.hand.com/">
  <wsdl:types>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://ws.demo.hap.hand.com/" elementFormDefault="unqualified" targetNamespace="http://ws.demo.hap.hand.com/" version="1.0">

  <xs:element name="sayHello" type="tns:sayHello"/>

  <xs:element name="sayHelloResponse" type="tns:sayHelloResponse"/>

  <xs:complexType name="sayHello">
    <xs:sequence>
      <xs:element minOccurs="0" name="arg0" type="xs:string"/>
      <xs:element minOccurs="0" name="arg1" type="tns:user"/>
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="user">
    <xs:complexContent>
      <xs:extension base="tns:baseDTO">
        <xs:sequence>
          <xs:element minOccurs="0" name="customerId" type="xs:long"/>
          <xs:element minOccurs="0" name="description" type="xs:string"/>
          <xs:element minOccurs="0" name="email" type="xs:string"/>
          <xs:element minOccurs="0" name="employeeCode" type="xs:string"/>
          <xs:element minOccurs="0" name="employeeId" type="xs:long"/>
          <xs:element minOccurs="0" name="employeeName" type="xs:string"/>
          <xs:element minOccurs="0" name="endActiveDate" type="xs:dateTime"/>
          <xs:element minOccurs="0" name="firstLogin" type="xs:string"/>
          <xs:element minOccurs="0" name="lastLoginDate" type="xs:dateTime"/>
          <xs:element minOccurs="0" name="lastPasswordUpdateDate" type="xs:dateTime"/>
          <xs:element minOccurs="0" name="password" type="xs:string"/>
          <xs:element minOccurs="0" name="passwordEncrypted" type="xs:string"/>
          <xs:element minOccurs="0" name="phone" type="xs:string"/>
          <xs:element minOccurs="0" name="startActiveDate" type="xs:dateTime"/>
          <xs:element minOccurs="0" name="status" type="xs:string"/>
          <xs:element minOccurs="0" name="supplierId" type="xs:long"/>
          <xs:element minOccurs="0" name="userId" type="xs:long"/>
          <xs:element minOccurs="0" name="userName" type="xs:string"/>
          <xs:element minOccurs="0" name="userType" type="xs:string"/>
        </xs:sequence>
      </xs:extension>
    </xs:complexContent>
  </xs:complexType>

  <xs:complexType name="baseDTO">
    <xs:sequence>
      <xs:element minOccurs="0" name="attribute1" type="xs:string"/>
      <xs:element minOccurs="0" name="attribute10" type="xs:string"/>
      <xs:element minOccurs="0" name="attribute11" type="xs:string"/>
      <xs:element minOccurs="0" name="attribute12" type="xs:string"/>
      <xs:element minOccurs="0" name="attribute13" type="xs:string"/>
      <xs:element minOccurs="0" name="attribute14" type="xs:string"/>
      <xs:element minOccurs="0" name="attribute15" type="xs:string"/>
      <xs:element minOccurs="0" name="attribute2" type="xs:string"/>
      <xs:element minOccurs="0" name="attribute3" type="xs:string"/>
      <xs:element minOccurs="0" name="attribute4" type="xs:string"/>
      <xs:element minOccurs="0" name="attribute5" type="xs:string"/>
      <xs:element minOccurs="0" name="attribute6" type="xs:string"/>
      <xs:element minOccurs="0" name="attribute7" type="xs:string"/>
      <xs:element minOccurs="0" name="attribute8" type="xs:string"/>
      <xs:element minOccurs="0" name="attribute9" type="xs:string"/>
      <xs:element minOccurs="0" name="attributeCategory" type="xs:string"/>
      <xs:element minOccurs="0" name="createdBy" type="xs:long"/>
      <xs:element minOccurs="0" name="creationDate" type="xs:dateTime"/>
      <xs:element minOccurs="0" name="lastUpdateDate" type="xs:dateTime"/>
      <xs:element minOccurs="0" name="lastUpdateLogin" type="xs:long"/>
      <xs:element minOccurs="0" name="lastUpdatedBy" type="xs:long"/>
      <xs:element minOccurs="0" name="objectVersionNumber" type="xs:long"/>
      <xs:element minOccurs="0" name="programId" type="xs:long"/>
      <xs:element minOccurs="0" name="requestId" type="xs:long"/>
      <xs:element minOccurs="0" name="sortname" type="xs:string"/>
      <xs:element minOccurs="0" name="sortorder" type="xs:string"/>
      <xs:element minOccurs="0" name="__id" type="xs:string"/>
      <xs:element minOccurs="0" name="__status" type="xs:string"/>
      <xs:element minOccurs="0" name="_token" type="xs:string"/>
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="sayHelloResponse">
    <xs:sequence>
      <xs:element minOccurs="0" name="return" type="tns:user"/>
    </xs:sequence>
  </xs:complexType>

</xs:schema>
  </wsdl:types>
  <wsdl:message name="sayHello">
    <wsdl:part element="tns:sayHello" name="parameters">
    </wsdl:part>
  </wsdl:message>
  <wsdl:message name="sayHelloResponse">
    <wsdl:part element="tns:sayHelloResponse" name="parameters">
    </wsdl:part>
  </wsdl:message>
  <wsdl:portType name="HelloWorld">
    <wsdl:operation name="sayHello">
      <wsdl:input message="tns:sayHello" name="sayHello">
    </wsdl:input>
      <wsdl:output message="tns:sayHelloResponse" name="sayHelloResponse">
    </wsdl:output>
    </wsdl:operation>
  </wsdl:portType>
  <wsdl:binding name="HelloGTSoapBinding" type="tns:HelloWorld">
    <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
    <wsdl:operation name="sayHello">
      <soap:operation soapAction="" style="document"/>
      <wsdl:input name="sayHello">
        <soap:body use="literal"/>
      </wsdl:input>
      <wsdl:output name="sayHelloResponse">
        <soap:body use="literal"/>
      </wsdl:output>
    </wsdl:operation>
  </wsdl:binding>
  <wsdl:service name="HelloGT">
    <wsdl:port binding="tns:HelloGTSoapBinding" name="HelloWorldImplPort">
      <soap:address location="http://172.16.1.94:8080/core/ws/HelloWorldService"/>
    </wsdl:port>
  </wsdl:service>
</wsdl:definitions>
  1. WSDL 端口:<portType> 元素是最重要的 WSDL 元素。

    它可描述一个 web service可被执行的操作,以及相关的消息。可以把 <portType> 元素比作传统编程语言中的一个类(或一个模块、或一个函数库)。

  2. WSDL 消息:<message> 元素定义一个操作的数据元素。

    每个消息均由一个或多个部件组成。可以把这些部件比作传统编程语言中一个方法调用的参数。

  3. WSDL types:<types> 元素定义 web service 使用的数据类型。

    为了最大程度的平台中立性,WSDL 使用 XML Schema 语法来定义数据类型。

  4. WSDL Bindings:<binding> 元素为每个端口定义消息格式和协议细节。

对于接口来说,接口文档非常重要,它描述如何访问接口。那么 WSDL 就可以看作 Web Service 接口的一种标准格式的“文档”。我们通过阅读 WSDL 就知道如何调用该 Web Service 接口了。

六、UDDI

Universal Description, Discovery and Integration",可译为“通用描述、发现与集成服务”,简称 UDDI。

WSDL 用来描述了访问特定的 Web Service 的一些相关的信息,那么在互联网上,或者是在企业的不同部门之间,如何来发现我们所需要的 Web Service 呢?而 Web Service 提供商又如何将自己开发的 Web Serivce 公布到互联网上呢?这就需要使用到 UDDI 了。

UDDI 是一个独立于平台的框架,用于通过使用 Internet 来描述服务,发现企业,并对企业服务进行集成。

UDDI 指的是通用描述、发现与集成服务

UDDI 是一种用于存储有关 web services 的信息的目录。

UDDI 是一种由 WSDL 描述的 web services 界面的目录。

UDDI 经由 SOAP 进行通信

UDDI 被构建入了微软的 .NET 平台

UDDI可以帮助 Web 服务提供商在互联网上发布 Web services的信息。UDDI 是一种目录服务,企业可以通过 UDDI 来注册和搜索 Web services。

但是实际上我们在开发项目的时候 UDDI 基本都没有用到,首先是 UDDI 规范做得并不算成功,现在使用得也并不多,其次是我们做的接口基本是实现企业内部系统之间的数据交互,很少在互联网上提供服务,因此也并不用注册 UDDI。

HAP 实现 Web Service 的方式是集成了 Apache 的 CXF 框架,如下图:

image

关于 CXF 我们下一章节再讲。通过这个框架开发和发布的 Web Service 通过Endpoint Address 即可访问,如 HAP 框架中的 Web Service:

image

在这个地址后面加上?WSDL即可访问,如:http://192.168.1.1:8080/core/ws/HelloWordService?wsdl

七、Web Service 体系结构

在Web Serivce的体系结构中涉及到三个角色,一个是 Web Service提供者,一个是 Web Service中介,还有一个就是 Web Service请求者;同时还涉及到三类动作,即发布,查找,绑定,

7.1 三个角色:

  1. Web Service 提供者:

    可以发布 Web Service,并且对使用自身服务的请求进行响应,Web Service的拥有者,它会等待其他的服务或者是应用程序访问自己。

  2. Web Service 请求者:

    也就是 Web Service功能的使用者,它通过服务注册中心也就是 Web Service中介者查找到所需要的服务,再利用 SOAP 消息向 Web Service提供者发送请求以获得服务。

  3. Web Service 中介:

    也称为服务代理,用来注册已经发布的 Web Service提供者,并对其进行分类,同时提供搜索服务,简单来说的话,Web Service 中介者的作用就是把一个 Web Service 请求者和合适的 Web Service 提供者联系在一起,充当一个管理者的角色,一般是通过 UDDI来实现。但是目前 UDDI 服务用得很少了,一般是通过接口服务地址直接访问,或者架设一个如 ESB 的中间件,用来连接 Web Service 提供者和 Web Service 请求者。

7.2 三个动作:

  1. 发布:

    通过发布操作,可以使 Web Serivce提供者向 Web Service中介注册自己的功能以及访问的接口。

  2. 发现(查找):

    使得 Web Service请求者可以通过 Web Service中介者来查找到特定种类的 Web Service 接口。

  3. 绑定:

    这里就是实现让Web Serivce请求者能够使用Web Serivce提供者提供的Web Serivce接口。

那么最后,Web Service 相较于 HTTP 直接传输数据有什么优点呢?

  • 接口中实现的方法和要求参数一目了然。

  • 不用担心大小写问题。

  • 不用担心中文urlencode问题。

  • 代码中不用多次声明认证(账号,密码)参数。

  • 传递参数可以为数组,对象等。

篇幅有限,关于 Web Service 的开发,我们下一章节见。

相关文章

网友评论

      本文标题:Web Service系列文章之一:概念梳理

      本文链接:https://www.haomeiwen.com/subject/jdgurftx.html