趣談網路協議---基於XML的SOAP協議:不要說NBA,請說美國職業籃球聯賽
阿新 • • 發佈:2018-12-13
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 檔案釋出到該註冊中心,客戶端可查詢到服務的描述,封裝為本地的客戶端進行呼叫。