1. 程式人生 > >趣談網路協議---基於XML的SOAP協議:不要說NBA,請說美國職業籃球聯賽

趣談網路協議---基於XML的SOAP協議:不要說NBA,請說美國職業籃球聯賽

ONC RPC 存在哪些問題?

ONC RPC 將客戶端要傳送的引數,及服務要傳送的回覆,都壓縮為一個二進位制串,存在不便。

  • 雙方的壓縮格式完全一致,一點都不能差,有一位不同都可能造成無法解壓縮。
  • 協議修改不靈活,業務發生改變時,修改了傳遞的引數,如果沒有及時通知對方,重新生成雙方的 Stub 程式,就會造成解壓縮不成功。
  • 版本問題。服務端提供的服務的引數格式為版本1,如果有一個客戶端需要加一個欄位,其餘上線的客戶端都要適配。
  • ONC RPC 的設計不是面向物件的。

XML 與 SOAP

SOAP 採用文字格式 XML 進行傳輸。

  • 格式不需要完全一致。比如不同欄位可互換位置。
  • 可靈活修改欄位。比如有的客戶端想增加一個欄位,不需要該欄位的客戶端不解析便可。
  • 面向物件,是更加接近使用者場景的表達方式。

如何將 XML 用在 RPC 中?

1、傳輸協議問題

基於 XML 最著名的通訊協議是 SOAP(Simple Object Access Protocol,簡單物件訪問協議),使用 XML 編寫簡單的請求和回覆訊息,並用 HTTP 協議傳輸。

SOAP 將請求和回覆放在一個信封裡,信封裡的信分擡頭和正文。

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 方法,給 www.geektime.com 傳送一個格式為 application/soap + xml 的 XML 正文,從而下一個單,該訂單封裝在 SOAP 信封中,並表明這是一筆交易(transaction),訂單詳情已寫明。

2、協議約定問題

雙方的協議約定是什麼樣的?如何對服務進行描述,方便客戶端呼叫?需要一種相對比較嚴謹的 Web 服務描述語言,WSDL(Web Service Discription Languages),也是一個 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>
  • 編寫 service。
 <wsdl:service name="PurchaseOrderServiceImplService">
  <wsdl:port binding="tns:purchaseOrderServiceSOAP" name="PurchaseOrderServiceImplPort">
   <soap:address location="http://www.geektime.com:8080/purchaseOrder" />
  </wsdl:port>
 </wsdl:service>

WSDL 可使用工具自動生成。也有工具根據 WSDL 生成客戶端 Stub。

3、服務發現問題

UDDI(Universal Description, Discovery and Integration),統一描述、發現和繼承協議,是一個註冊中心,服務提供方可將 WSDL 檔案釋出到該註冊中心,客戶端可查詢到服務的描述,封裝為本地的客戶端進行呼叫。