消息編碼
隨著時間的流逝,也許我們會條件反射式地認為XML(SOAP)是一個結構文本 。畢竟,文本是人可讀的,每個計算機系統也可以處理文本。基於文本的XML的 普遍共性與我們的與其它系統交互的想法產生了共鳴。可以容易的解釋的基於文 本的XML本質上會體積變大。可以理解使用XML會帶來性能損失。就像要花費點精 力把信裝到信封裡一樣,它需要一些處理時間與XML交互。某些情況下,基於文 本的XML數據大小限制了它的應用,特別是當我們要通過網絡發送一個XML消息的 時候。
此外,如果我們限制自己使用基於文本的XML,那麼我們怎麼才能在XML文檔 裡發送二進制數據(像音樂或者視頻)?如果你已經閱讀了標准的XMLSchema數 據類型,你會發現2個二進制數據類型:: xs:base64Binary 和xs:hexBinary。 本質上說,兩個數據類型都代表一組有序的8位字節。使用這些XML數據類型或許 可以解決一些嵌入二進制數據到文檔中的問題,但是事實上,這已經使得性能問 題更加糟糕。眾所周知的問題就是,base64編碼會增加數據30%的大小。這個情 況對於xs:hexBinary更壞,因為它會增加位原來的2倍大小。兩個數據都是基於 UTF-8編碼的假設。如果我們采用UTF-16編碼,這些倍數因子都會翻倍增加。
XML 信息集( XML Infoset)
為了找到性能的瓶頸的答案,我們詳細來看一下XML文檔的結構。如果我們看 一下規范,XML是一個精確的撰寫結構化數據的語法(定義在 http://www.w3.org/TR/REC-xml/)。它要求定義格式良好的XML文檔必須包涵一 個開始和結束元素、一個根節點等等。奇怪的是,XML規范發布以後,激起了抽 象定義XML文檔的需求。XML信息集(定義在http://www.w3.org/TR/xml- infoset/)提供了這個抽象定義。
實際上,XML信息集定義是項目之間的關系,不定義任何具體的語法,我們能 夠解釋許多不同的消息編碼,包括一些比文本更高校的編碼格式,而不需要修改 我們的程序。
SOAP和XML信息集
記得SOAP是建立在XML之上的。這個產生一個問題:到底SOAP消息是建立在早 期的XML語法上還是XML信息集上呢?答案是2者都有。2個SOAP規范並存:SOAP 1.1 和SOAP 1.2。SOAP1.1建立在舊的XML語法上,SOAP1.2建立在XML 信息集上 。有這麼一個事實,就可以猜想SOAP1.2建立的消息SOAP1.1的解析器可能無法閱 讀。WCF是建立在SOAP1.2(XML信息集上),但是它可以同時處理SOAP 1.1 和 SOAP 1.2的消息。
WCF可以用來和定制與其它實際的消息編碼一起工作,只要消息是遵照 SOAP1.1或者SOAP1.2的(它可以和不是SOAP消息一起工作)。如你將會在接下來 的章節裡看到的一樣,WCF是一個可靈活接入和組合的架構。所以自定義編碼器 可以輕易地安裝到WCF的管道上。當一個新的編碼器開發完畢,微軟或者第三方 都可以在消息堆棧裡創建和插入它。我將會在第6章:《通道》裡詳細介紹消息 編碼器。現在我們來看一下WCF裡的編碼器。在寫本書的時候,WCF提供了三個編 碼器:文本(text)、(二進制)binary、 消息傳輸優化機制(Message Transmission Optimization Mechanism ,MTOM)。
文本編碼器
和你從它的名字裡猜到的一樣,文本編輯器的輸出結果是基於文本編碼的消 息。每個明白Unicode文本的系統都可以閱讀和處理這個編碼器傳遞來的消息, 在與別的非WCF系統互操作時,這個是一個很幫的選擇。二進制數據通過 xs:base64Binary擴展樣式定義(XSD)數據類型可以包涵到基於文本的消息裡。 這是一個使用WCF文本編碼器編碼過的消息(為了清晰,移除了一部分元素)。
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap- envelope">
<s:Header></s:Header>
<s:Body>
<SubmitOrder xmlns="http://wintellect.com/OrderProcess">
<Order xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<OrderByte xmlns="http://wintellect.com/Order">
mktjxwyxKr/9oW/jO48IhUwrZvNOdyuuquZEAIcy08aa+HXkT3dNmvE/
+zI96Q91a9Zb17HtrCIgtBwmbSk4ys2pSEMaIzXV3cwCD3z4ccDWzpWx1/
wUrEtSxJtaJi3HBzBlk6DMW0eghvnl652lKEJcUJ6Uh/LRlZz3x1+aereeOgdLkt4gCnNO EFECL8CtrJtY/taPM4A+k/
4E1JPnBgtCRrGWWpVkO0UqRXahz2XbShrDQnzgDwaHDf/
fHDXfZgpFwOgPF1IG88KQZO0JncSYKIp5I8OPYTeqD0yVhB8QSt9sWw59yzLHvU65UKoYf XA7RvOqZkJGtV6wZAgGcA=
=
</OrderByte>
<OrderNumber xmlns="http://wintellect.com/Order">
12345
</OrderNumber>
</Order>
</SubmitOrder>
</s:Body>
</s:Envelope>
二進制編碼器
二進制編碼器是最高效的消息編碼器,並且只適用與WCF-到-WCF的通信。在 WCF所有的編碼器中,二進制編碼器產生最小的消息。記住這個編碼器產生一個 序列化的信息集,即使它是二進制編碼格式。將來可能,一個標准的二進制編碼 會被采用,這些編碼的類型可以顯著第改善消息應用的性能。
MTOM編碼器
MTOM編碼器根據MTOM規范創建消息。(MTOM規范可以在這裡查到 http://www.w3.org/TR/soap12-mtom/)因為MTOM編碼已經規范化,所以其它廠 商可以自由創建發送和接受消息的基礎結構。結果,MTOM消息編碼的WCF消息就 可以發送給非WCF的應用(只要它們理解MTOM)。通常來說,MTOM為了允許高效 第傳輸包涵二進制數據的消息,它也提供了數字簽名。MTOM消息編碼可以通過多 用途網絡郵件擴展協議(MIME)啟用這些特性。MTOM消息的內容被XML-二進制優 化包裝方法所定義。更多信息:http://www.w3.org/TR/xop10/.
在運行時,MTOM編碼器為了數字簽名創建一個基於base64編碼的代表,讓原 始二進制數據可以在消息裡打包。一個MTOM消息看起來如下:
// start of a boundary in the multipart message多部分 消息的分界線
--uuid:+id=1
Content-ID: <http://wintellect.com/0>
Content-Transfer-Encoding: 8bit
// set the content type to xop+xml,設置內容類型xop+xml
Content-Type: application/xop+xml;charset=utf8; type="application/soap+xml"
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap- envelope">
<s:Header></s:Header>
<s:Body>
<SubmitOrder xmlns="http://wintellect.com/OrderProcess">
<order xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<OrderByte xmlns="http://wintellect.com/Order">
// add a reference to another message part
<xop:Include href=cid:http://wintellect.com/1/12345
xmlns:xop="http://www.w3.org/2004/08/xop/include"/>
</OrderByte>
<OrderNumber xmlns="http://wintellect.com/Order">
12345
</OrderNumber>
</order>
</SubmitOrder>
</s:Body>
</s:Envelope>
// end of the boundary in the first message part第一部分的 內容結束邊界
--uuid:+id=1
// add the binary data as an octect stream增加二進制數據為八 位字節流
Content-ID: <http://wintellect.com/1/12345>
Content-Transfer-Encoding: binary
Content-Type: application/octet-stream
// raw binary data here這裡是原始二進制數據
注意到二進制數據被原樣保坤在SOAP消息裡的另一塊區域裡。因為二進制數 據被打包到SOAP消息的外部區域,那麼這麼才能給SOAP進行數字簽名呢?如果我 們使用基於XML的安全機制,像XML加密和XML數字簽名裡描述的一樣,我們不能 引用外部的二進制流。這些加密個簽名機制要求被保護的數據包裝在SOAP消息裡 。咋一看,對於多部分的消息還真沒有什麼辦法。事實上,這是直接網絡消息封 裝(DIME)和SOAP附件的致命弱點。MTOM提供了一個有趣的解決辦法。
MTOM編碼規范規定一個MTOM消息能夠包涵二進制數據在base64編碼的字符裡 ,後者二進制流在額外的消息部分裡。它也表示一個基於base64編碼的二進制數 據的代表在處理的時候必須可用。換句話說,額外的消息部分可以為消息傳輸創 建,但是內聯的base64數據必須對一些操作如:應用數字簽名臨時可用。當消息 處於內聯的基於base64編碼的狀態,基於XML編碼的安全機制可以被應用到SOAP 消息裡。安全機制應用結束,消息可以被序列化為多部分消息。當接受者接受消 息的時候,這個消息可以被XML安全規范機制強制根據一些列規則進行驗證。
非常有意思地看到,當大量二進制消息是基於base64編碼或者二進制流編碼 在額外的消息部分的時候,WCF MTOM編碼器能夠正確地選擇序列化。WCF編碼器 使用二進制數據大小作為選擇的依據。在之前的消息裡,OrderBytes元素大約 800k。如果我們減少OrderBytes的大小到128k,在檢查一下消息格式,我們可以 看到:
// start of a boundary in the multipart message,多部 分消息開始邊界
--uuid:+id=1
Content-ID: <http://wintellect.com/0>
Content-Transfer-Encoding: 8bit
// set the content type to xop+xml
Content-Type: application/xop+xml;charset=utf8; type="application/soap+xml"
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap- envelope">
<s:Header></s:Header>
<s:Body>
<SubmitOrder xmlns="http://wintellect.com/OrderProcess">
<order xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<OrderByte xmlns="http://wintellect.com/Order">
kF+k2CQd/lCitSYvXnLhuOtaMCk/tZaFZIWeW7keC3YvgstAWoht/wiOiR5+HZPo+TzYoH +qE9vJHnSefqKXg6mw/
9ymoV1i7TEhsCt3BkfytmF9Rmv3hW7wdjsUzoBl9gZ1zR62QVjedbJNiWKvUhgtq8hAGjw +uXlttSohTh6xu7kkAjgoO
3QJntG4qfwMQCQj5iO4JdzJNhSkSYwtvCaTnM2oi0/fBHBUN3trhRB9YXQG/mj7+ZbdWss kg/
Lo2+GrJAwuY7XUROKyY+5hXrAEJ+cXJr6+mKM3yzCDu4B9bFuZv2ADTv6/MbmFSJWnfPwb H1wK0LQi7Ixo95iF
</OrderByte>
<OrderNumber xmlns="http://wintellect.com/Order">
12345
</OrderNumber>
</order>
</SubmitOrder>
</s:Body>
</s:Envelope>
--uuid:+id=1-
這個例子裡,WCF編碼器序列化二進制元素為基於base64編碼的string。這個 優化是相當符合MTOM規范。
選擇恰當的編碼
選擇消息編碼器強迫你去考慮當前和未來的消息使用問題。大部分來說,應 用互操作性和消息裡的數據類型會決定我們的選擇。性能,在決定那個編碼器是 最適合我們系統的時候,也會考慮進來。表2-1基於消息類型和那種系統可以可 以發送和接受消息列舉了編碼情況。
表 2-1:消息編碼器排列和場景
消息類型 Binary Text MTOM Text內容, 只與WCF 交互 1 2 3 Text內容, 與現代非WCF系統交互 N/A 1 2 Text內容, 與舊的非WCF systems 交互 N/A 1 N/A 大二進制內容, 只與WCF 交互 1 3 2 大二進制內容, 與現代非WCF系統交互 N/A 2 1 大二進制內容, , 與舊的非WCF systems 交互 N/A 1 N/A 小二進制內容, 只與WCF 交互 1 2 3 小二進制內容, 與現代非WCF系統交互 N/A 1 2 小二進制內容, , 與舊的非WCF systems 交互 N/A 1 N/A不應該驚訝,二進制編碼器是WCF與其它WCF系統交互最高效的編碼器。我們 也許吃驚的是這個事實,在端到端的情況下,MTOM消息編碼是比文本編碼器效率 還低。互操作性和二進制數據大小是你選擇MTOM和文本編碼器的因素。絕大多數 情況,MTOM編碼消息只能發送給MTOM編碼器的系統。寫本書的時候,MTOM是一個 很新的規范,所以只有現代系統可以高效地處理MTOM消息。從性能的角度來看, MTOM編碼器只有當包裝到消息裡的二進制數據很大的時候才有意義。MTOM不應該 用在不包括二進制數據的消息裡,因為MTOM的性能此時比文本編碼器效率更低。 因此,獨立測試一個在產品環境裡使用的消息非常重要。
幸運的是,我們可以在第4章:WCF 101裡看到,WCF就是這些編碼選擇都不需 要大的改變應用程序的方式來設計的。事實上,這使得一個服務可以與多種不同 的消息編碼交互成為可能。舉例來說,一個服務可以與兩個二進制編碼和文本編 碼的消息交互。這個場景的好處在於當與別的WCF參與者通信的時候,服務可以 快速執行,並且可以與別的平台通信,比如JAVA。
【地址】:http://www.cnblogs.com/frank_xl/