ONE RPC将客户端发送的参数,服务端发送的回复,都压缩在了一个二进制串里面,这样虽然可以解决双方的约定问题,但是有些不方便

首先,需要双方的压缩格式完全一致,一点不能有差错,因为出现了一点的错误,就会导致无法解压缩

其次,对于协议的修改,并不灵活,如果不是传输过程中的错误,而是因为客户端进行了相关的修改,但是没有告诉服务端,或者反之,就会导致传输的失败

这种使用的方式灵活性,灵活性太差了,就会导致每次只要一个小改动,就需要重新编写Stub程序

如果是沟通的话,还好说,如果提供了一个服务,有很多客户端都在用,现在有个需求,加了一个新字段,导致所有客户端都需要重写,加上这个字段,怎么办呢?

最后,原本的ONE RPC的设计师面向函数的,而非面向对象的,所以现在的面向对象的思想有所冲突\

所以,为了进行相对应的修改,我们需要加强RPC的规则

1.XML和SOAP

我们可以做一个通用类型的文本,只要能够拿到文本,就能知道其含义

常见的文本类的格式是XML ,如下的例子

<?xml version=”1.0″ encoding=”UTF-8″?>

<geek:purchaseOrder xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xmlns:geek=”http://www.example.com/geek”>

<order>

<date>2018-07-01</date>

<className>趣谈网络协议</className>

<Author>刘超</Author>

<price>68</price>

</order>

</geek:purchaseOrder>

XML的格式简单清晰,明了

可以一眼的读取出来

而且,即使顺序变了,也不影响客户端和服务端的解析

而且即使有多的字段,也没有问题,因为客户端即使拿到了对应的XML文件,只要不解析对应的字段就可以了

那么如何使用在RPC之中呢?

传输协议问题

如何使用,基于XML的著名通信协议就是SOAP,全程就是简单对象访问协议 Simple Object Access Protocol

使用XML编写简单的请求和回复消息,并且使用HTTP协议进行传输

SOAP将请求和回复挡在一个信封,并且使用HTTP进行发送

请求的格式如下

POST /purchaseOrder HTTP/1.1

Host: www.geektime.com

Content-Type: application/soap+xml; charset=utf-8

Content-Length: nnn

<?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>

<m:Trans xmlns:m=”http://www.w3schools.com/transaction/”

soap:mustUnderstand=”1″>1234

</m:Trans>

</soap:Header>

<soap:Body xmlns:m=”http://www.geektime.com/perchaseOrder”>

<m:purchaseOrder”>

<order>

<date>2018-07-01</date>

<className>趣谈网络协议</className>

<Author>刘超</Author>

<price>68</price>

</order>

</m:purchaseOrder>

</soap:Body>

</soap:Envelope>

使用HTTP协议的POST方法,发送了一个格式为application/soapxml的XML正文,在这个HTTP协议中,说明对应的格式

协议的约定问题

因为服务开发出来了,是给陌生人用的,对于客户端来说,如何拿到上面的格式,当然,可以写文档,放在官方网站上,但是文档并不一定更新及时,而且文档并不一定严谨,所以,开发出了一种相对严谨的Web服务描述语言,WSDL,是一个XML文件

在这个文件中,定义一个order,和上面的XML对应起来

 <wsdl:types>

<xsd:schema targetNamespace=”http://www.example.org/geektime”>

<xsd:complexType name=”order”>

<xsd:element name=”date” type=”xsd:string”></xsd:element>

<xsd:element name=”className” type=”xsd:string”></xsd:element>

<xsd:element name=”Author” type=”xsd:string”></xsd:element>

<xsd:element name=”price” type=”xsd:int”></xsd:element>

</xsd:complexType>

</xsd:schema>

</wsdl:types>

作为一个描述层

然后呢,定义对应的message格式

 <wsdl:message name=”purchase”>

<wsdl:part name=”purchaseOrder” element=”tns:order”></wsdl:part>

</wsdl:message>

最后,暴露一个端口

 <wsdl:portType name=”PurchaseOrderService”>

<wsdl:operation name=”purchase”>

<wsdl:input message=”tns:purchase”></wsdl:input>

<wsdl:output message=”……”></wsdl:output>

</wsdl:operation>

</wsdl:portType>

编写一个binding,然后将上面的信息绑定到SOAP请求的body里面

 <wsdl:binding name=”purchaseOrderServiceSOAP” type=”tns:PurchaseOrderService”>

<soap:binding style=”rpc”

transport=”http://schemas.xmlsoap.org/soap/http” />

<wsdl:operation name=”purchase”>

<wsdl:input>

<soap:body use=”literal” />

</wsdl:input>

<wsdl:output>

<soap:body use=”literal” />

</wsdl:output>

</wsdl:operation>

</wsdl:binding>

对于某个服务,哪怕是个陌生人,都可以去调用获取到这个文件,哪怕这个文件比较复杂,难以看懂,也可以利用工具进行解析,然后进行调用

服务发现问题

如何发现服务,可以使用UDDI,统一描述,发现和集成协议,作为一个注册中心,服务提供方将上面的WSDL描述文件,发布到这个注册中心,注册完毕了,服务使用方可以查找到服务的描述,封装为本地的客户端使用

本章小结

对于原本的二进制RPC框架,缺点很多,格式要求严格,修改不方便,于是出现了基于文本的调用方式

SOAP,SOAP有着三大要素,协议约定用的WSDL,传输协议用HTTP,服务发现也能够UDDL

课后思考

1.对于HTTP协议,很多方法,但是SOAP只用了POST

2.基于文本的RPC虽然解决了二进制的问题,但是SOAP还是很复杂的,有更方便的吗?

1.SOAP不是只能通过HTTP传输,还有着SOAP binding

虽然http协议中有着post,get,head,put,delete等多种方法,但是一般post get足够使用,所以soap只支持post方法的差别应该在缺少get方法,get方法可以让浏览器直接跳转,post必须借助表单或者ajax才能提交,限制了soap在页面内获取数据或者提交数据

soap的协议里是支持get的,但是由于XML文件比较复杂,不太适合放在get请求的参数里面

所以一般采用post

2.SOAP的HTTP Binding支持很完整的Web Method. GET/POST都可以

而且只使用POST,不如GET请求那么方便

对于方便的协议,可以考虑restful协议

发表评论

邮箱地址不会被公开。 必填项已用*标注