閻瑋,施亮
在網(wǎng)絡(luò)傳輸世界中,XML[1](Extensible Markup Language 可擴展標(biāo)記語言)正逐漸成為Web服務(wù)的通用語言。但是,XML的靈活性對網(wǎng)絡(luò)基礎(chǔ)設(shè)施提出了很高的要求。實際上,執(zhí)行轉(zhuǎn)換、壓縮和Web服務(wù)安全等CPU密集型任務(wù)可消耗多達(dá)80%的服務(wù)器處理能力。據(jù)結(jié)構(gòu)化信息標(biāo)準(zhǔn)促進(jìn)組織(Organization for the Advancement of Structured Information Standards)統(tǒng)計,由于XML的自我描述復(fù)雜性,計算機處理描述相同信息量的XML文檔要比相應(yīng)二進(jìn)制文檔多消耗 25倍的計算資源[2]。于是,以網(wǎng)絡(luò)硬件或通信加速設(shè)備面目出現(xiàn)的 XML加速器應(yīng)運而生。XML 加速器(XML Accelerator)可以降低應(yīng)用服務(wù)器的處理負(fù)荷,除了處理XML數(shù)據(jù)外,還有助于執(zhí)行安全數(shù)據(jù)交換,并支持服務(wù)質(zhì)量(QoS)[3]。
本文介紹了XML加速器的基本原理,著重對硬件加速的關(guān)鍵環(huán)節(jié)---XML解析過程進(jìn)行了探討,較為詳細(xì)地闡述了一種新的解析技術(shù)VTD-XML,分析它的性能優(yōu)勢和硬件實現(xiàn)前景,并給出了系統(tǒng)結(jié)構(gòu)圖。
XML加速設(shè)備通常部署在數(shù)據(jù)中心的3層架構(gòu)中,置于防火墻之后,負(fù)載均衡器和應(yīng)用服務(wù)器(或兼具應(yīng)用服務(wù)器和Web 服務(wù)器功能的設(shè)備)之間。負(fù)載均衡器負(fù)責(zé)將負(fù)載平均分布于XML加速器;應(yīng)用服務(wù)器是XML 數(shù)據(jù)的主要制造者,同時也是最大的消費者。XML加速器在執(zhí)行諸如解析、確認(rèn)、轉(zhuǎn)換和壓縮等操作時,其速度要比應(yīng)用服務(wù)器快得多,因為它是專為特定任務(wù)度身定制的。
XML流量可分為輸入和輸出數(shù)據(jù)流。對于輸入流量,XML加速器負(fù)責(zé)解壓、解密、確認(rèn)和路由等工作,并處理HTTP 或SOAP(簡單對象訪問協(xié)議)報頭和XML內(nèi)容。它根據(jù)配置信息決定如何進(jìn)行轉(zhuǎn)換、驗證或還原內(nèi)容等工作。相應(yīng)地,負(fù)載均衡器被配置為將經(jīng)過選擇的正確數(shù)據(jù)傳送給XML加速器。例如,根據(jù)某個正從負(fù)載均衡器流向應(yīng)用服務(wù)器的HTTP報頭,XML加速器便可獲知該數(shù)據(jù)是否已被壓縮。
對于輸出流量,XML加速器對從應(yīng)用服務(wù)器流向負(fù)載均衡器的流量進(jìn)行內(nèi)容轉(zhuǎn)換。當(dāng)XML內(nèi)容流經(jīng)時,文件或配置中的參考樣式表即被應(yīng)用到文件中,并將其轉(zhuǎn)換為HTML、無線標(biāo)記語言(Wireless Markup Language)或其他形式的XML。此外,通過配置負(fù)載均衡器和Web服務(wù)器,XML加速器還可加快XML數(shù)據(jù)的加密和壓縮。通常,XML加速器可以以線速運行,而這是應(yīng)用服務(wù)器望塵莫及的。
在安全管理方面,XML加速器承擔(dān)著網(wǎng)關(guān)的角色,負(fù)責(zé)對輸入輸出流量進(jìn)行加解密、驗證和授權(quán)操作。雖然在這種情況下,性能未必得到提高,但卻可以對 Web業(yè)務(wù)數(shù)據(jù)進(jìn)行有效控制。
圖1 XML加速器工作原理
下面對XML加速器的工作模式進(jìn)行簡要的說明:
①負(fù)載均衡器接收來自Internet的輸入流量。
②負(fù)載均衡器將XML流量引向XML加速器。
③XML加速器對 XML流量進(jìn)行解壓、解析、解密和確認(rèn)后,把它們路由給適當(dāng)?shù)膽?yīng)用服務(wù)器。
④XML加速器接收來自應(yīng)用服務(wù)器的流量,并對它們進(jìn)行轉(zhuǎn)換、確認(rèn)、加密和壓縮。
⑤XML加速器向負(fù)載均衡器發(fā)送XML數(shù)據(jù),并將其傳向Internet。
如圖1所示,XML加速器把原來由應(yīng)用服務(wù)器承擔(dān)的許多大量耗費CPU時間的任務(wù)卸載到網(wǎng)絡(luò)上,從而提高系統(tǒng)性能,并有助于實施安全數(shù)據(jù)交換和服務(wù)質(zhì)量。
影響XML處理速度的因素主要包括3個:網(wǎng)絡(luò)傳輸時間、消息處理時間和服務(wù)執(zhí)行時間。在消息處理階段中,XML解析是最消耗時間的一個環(huán)節(jié)。所謂解析就是用某種方法來提取其中的元素、屬性和數(shù)據(jù),以便用這些信息進(jìn)行進(jìn)一步的操作,例如用提取出的某些符合條件的信息與客戶端交互。對于那些需要處理大量數(shù)據(jù)的應(yīng)用程序,這種技術(shù)尤為重要。選擇合適的解析技術(shù)對應(yīng)用系統(tǒng)的性能有著較大的影響,不正確的解析會導(dǎo)致過度的內(nèi)存消耗和過長的處理時間,從而大大降低系統(tǒng)的整體性能。
通常,根據(jù)解析方式的不同,我們大致有兩種選擇:基于樹的DOM(Document Object Model文檔對象模型)和基于事件的SAX(Simple API for XML 簡單應(yīng)用編程接口)。前者是W3C推薦的標(biāo)準(zhǔn)模型,它將XML的結(jié)構(gòu)信息以樹形的方式構(gòu)建,提供了遍歷這顆樹的接口與方法?;贒OM的解析必須將XML文檔整個讀入內(nèi)存中,所以當(dāng)遇到較大的XML文檔時,解析過程會變得較慢而且非常消耗內(nèi)存。而SAX模型是串行操作的,逐個元素的向前只讀處理,整個文檔并不一次性地讀入內(nèi)存,這樣就避免了處理大型文檔時的速度問題,但是由于沒有結(jié)構(gòu)信息,無法遍歷操作,可維護性比較差。兩種方式各有利弊,都不是特別理想的解決方案,表1對他們的優(yōu)缺點作了總結(jié)。
表1 兩種解析方式的比較
可以看出,DOM和SAX基本上是正好相反的兩個極端,兩者都不能很好的滿足XML加速的要求。所以我們選擇了另外一種處理技術(shù),它既有很好的易用性,占用內(nèi)存少,而且運行速度也很高。這就是VTD-XML解析技術(shù)。
VTD-XML(Virtual Token Descriptor,虛擬令牌描述符)是一種新型的、開源的、非提取性的XML處理方式。非提取的意思,即解析器將XML文檔視為一個大標(biāo)記筐,并創(chuàng)建詳細(xì)描述XML中標(biāo)記位置的地圖,解析器會將標(biāo)記與原文中保持一樣[4]。它能夠?qū)崿F(xiàn)數(shù)據(jù)的隨機存取,而不會導(dǎo)致過多的資源浪費,這很好地解決了DOM占用內(nèi)存過大的缺點。
在DOM中,內(nèi)存的表達(dá)包括大量由指示器縫合起來的節(jié)點對象(無論網(wǎng)元、文本、CDATA或?qū)傩裕?。把一切?dāng)做節(jié)點對象的例程會降低性能,同時增加內(nèi)存使用開銷。這是DOM處理速度緩慢的一個主要原因。
VTD技術(shù)的關(guān)鍵優(yōu)化就在于它采用非提取性的令牌環(huán)結(jié)構(gòu)。VTD-XML在內(nèi)存中保存完整及未解碼的XML消息,并使用一個二進(jìn)制編碼規(guī)范來唯一地表示每個符號。這種規(guī)范被稱為Virtual Token Descriptor(虛擬符號描述符)。每個VTD記錄都是一個64位長的數(shù)據(jù)類型(如圖2所示),它對XML中符號的長度、起始偏移量、類型、嵌套深度進(jìn)行了編碼。
圖2 VTD記錄的數(shù)位分布
VTD記錄固定長度的目的就是為了提高性能,因為長度固定在讀取、查詢等操作的時候格外的高效,也就是可以用數(shù)組這種高效的結(jié)構(gòu)來組織 VTD,從而大大減少了因為大量使用對象而產(chǎn)生的性能問題。它能夠?qū)ML這種樹形的數(shù)據(jù)結(jié)構(gòu)簡單地變換成對一個字節(jié)數(shù)組的操作。舉例來說,如果要查找一個元素并刪除它,那么只需要找到這個元素的VTD,將這個VTD從VTD數(shù)組中刪除,然后再將所有的VTD寫出到另一個數(shù)組中就可以了,因為刪除的VTD標(biāo)明了要刪除的元素的位置,所以在新寫入的數(shù)組中就不會出現(xiàn)這段元素了。這就是所謂的增量更新,其效率相當(dāng)?shù)母摺?/p>
關(guān)于遍歷方式,VTD-XML采用位置緩存LC(Location Cache),簡單來說就是以VTD深度作為標(biāo)準(zhǔn)構(gòu)建一個樹形的表結(jié)構(gòu)。LC的條目也是64位長的數(shù)值類型,前32位代表一個VTD的索引,后32位代表了這個VTD的第一個孩子的索引。利用這些信息就可以計算出任何想要到達(dá)的位置了。
具體解析處理過程如下:
(1)首先建立一個內(nèi)存數(shù)組,把要解析的 XML文檔讀入數(shù)組。
(2)使用VTDGen類:創(chuàng)建一個VTDGen類對象,使用成員函數(shù)setDoc把數(shù)組中的值賦給VTDGen對象,然后調(diào)用Parse方法產(chǎn)生VTD緩存記錄和記錄的層次信息。
(3)使用VTDNav方法導(dǎo)航定位:主要的導(dǎo)航功能是toElement。使用 ROOT、PARENT、FIRST_CHILD、LAST_CHILD、NEXT_SIBLING和PREV_SIBLING這六個預(yù)先確定的值來完成導(dǎo)航定位。
(4)用Autopilot方法遍歷結(jié)點,并支持XPath處理功能。
在了解了VTD-XML的基本原理后,下面將把VTD獨有的性能特點和其他的解析技術(shù)進(jìn)行統(tǒng)一的比較。
VTD-XML的層次結(jié)構(gòu)僅僅是由元素的節(jié)點組成,而在DOM中,無論是屬性節(jié)點還是文本節(jié)點都被認(rèn)為是節(jié)點的一部分,都能夠成為它層次結(jié)構(gòu)的一部分。另一方面,在VTD-XML中,有且僅有一個用于VTD遍歷的指針。該指針不能被復(fù)制,但可以暫時地將指針地址保存在全局的堆棧中。VTDNav有兩個堆棧存取的函數(shù),push()和pop()。假設(shè)指針現(xiàn)在位于元素結(jié)構(gòu)信息中的某處,記錄下該位置,然后將指針移向文檔的另一個部分,但希望仍能夠回到原先保留的位置。為了實現(xiàn)這樣一個過程,我們首先要調(diào)用 push()函數(shù),將位置信息保存進(jìn)堆棧。然后,在指針移到文檔其他位置后,我們?nèi)钥梢酝ㄟ^ pop()函數(shù),快速返回剛才所記錄的位置。
VTD-XML最獨特的一個方面,就是它基于虛擬令牌描述符的“非提?。╪on-extractive)”特點,這使它明顯區(qū)別于任何其他的解析程序。非提取式解析是 VTD-XML能夠達(dá)到最佳處理性能和內(nèi)存節(jié)省的關(guān)鍵技術(shù)。VTD-XML是通過如下方式實現(xiàn)它的非提取性能的。
第一,很多 VTDNav的函數(shù),比如 getAttrVal(),getCurrentIndex()和getText()都會返回一個整數(shù)。這個整數(shù)實際上是一個VTD記錄的索引,用于調(diào)用函數(shù)時描述所需令牌。解析之后,VTD-XML會產(chǎn)生一個由VTD記錄構(gòu)成的線性緩沖區(qū)。因為VTD記錄長度固定,所以只要知道信息的索引值就可以在緩沖區(qū)中獲取任何的記錄。要注意的是,VTD記錄都不是對象,因此不能夠通過指針設(shè)定地址值。當(dāng) VTDNav函數(shù)沒有計算出任何有意義的值時,它會返回-1,這個值類似DOM中的空指針。
第二,因為解析程序并不產(chǎn)生任何字符對象(畢竟令牌是虛擬構(gòu)建的),VTD-XML是直接在VTD記錄中進(jìn)行比較對照的操作。比如,VTDNav的matchElement()函數(shù)用于測試VTD指針記錄的元素名是否與給定的字符相匹配。相似的 VTDNav函數(shù),比如 matchTokenString()、matchRawTokenString()和matchNormalizedTokenString()函數(shù)雖然都有各自的不同點,但都能夠在字符和VTD記錄中進(jìn)行直接的比較。這樣做的好處在于,用戶完全不需要自己將令牌放入字符對象中。自行創(chuàng)建對象并將令牌存入是比較復(fù)雜的,尤其在大量創(chuàng)建對象的時候更是十分繁瑣的工作。避免了對象的大量創(chuàng)建是VTD-XML性能顯著優(yōu)于DOM和SAX的主要原因。
這里有一組數(shù)據(jù),取自于VTD-XML的官方網(wǎng)站[5]:
VTD-XML的解析速度是 SAX(with NULL content handler)的1.5x~2.0x。With NULL content handler的意思就是說 SAX解析中沒有插入任何額外的處理邏輯,也就是SAX的最高速度。VTD-XML的內(nèi)存占用是原 XML的1.3x~1.5x(其中 1.0x的部分是原 XML,0.3x~0.5x是VTD-XML占用的部分),而DOM的內(nèi)存占用則是原XML的 5x~10x。
內(nèi)存占用率上的重大優(yōu)勢使得 VTD-XML可以被用于處理大XML文檔,并且對任意大小的文件都有較好的性能。
VTD-XML是一個開源項目,目前有C、C#、JAVA三種平臺支持。對它的研究仍然有許多改進(jìn)與完善的空間,比如它在硬件上的應(yīng)用。我們研究的最終目標(biāo)是將VTD解析移植到芯片上(本實驗室采用的是 Altera NIOSⅡ硬件平臺),連同TCP/IP協(xié)議棧、HTTP協(xié)議、SOAP處理器以及建立于 SOAP之上的服務(wù)邏輯等模塊一起,共同組成整個XML加速系統(tǒng),系統(tǒng)架構(gòu)如圖3所示。
圖3 系統(tǒng)總體架構(gòu)
在多數(shù)XML處理過程中,問題在于將數(shù)據(jù)處理帶到芯片級別時,并不是依靠XML本身來完成的,就像XML所使用的處理模型一樣。舉例來說,DOM和SAX,兩者都需要構(gòu)建一個復(fù)雜的內(nèi)存中的數(shù)據(jù)結(jié)構(gòu),以及在這些模型中任意向前瀏覽或向后瀏覽的能力。它們還使用動態(tài)數(shù)據(jù)結(jié)構(gòu),這種結(jié)構(gòu)會隨著時間不斷變化,并且截取任意大小的數(shù)據(jù)塊(有時候會非常大)。在某種情況下,這些會引起處理器與硅芯片之間映射的問題,導(dǎo)致難于應(yīng)用,或者是降低芯片的工作效率,達(dá)不到最好的處理效果。在將特定的處理任務(wù)固化到硅芯片之中的過程中,它們并沒有真正提供一種性能或處理特長,能夠用來調(diào)整必要的工作。
VTD-XML技術(shù)正是在上述背景下產(chǎn)生的,并且發(fā)展迅速。這種模型在內(nèi)存中保留了一份XML原始的文檔(可以被分割成塊),然后將這份文檔利用令牌形式分割成固定大小的64位數(shù)據(jù)塊。這種處理方式有很多好處。首先,該處理方式和加密/解密以及包數(shù)據(jù)的分割/組裝操作類似,而后者已經(jīng)被廣泛的認(rèn)可并應(yīng)用到硅芯片之中[6]?,F(xiàn)在,我們又有了用于XML處理的模型,能夠幫助我們把軟件程序移植到硬件芯片中,并且保留其中的性能和處理優(yōu)點。可以預(yù)見這項技術(shù)必會大大促進(jìn)XML硬件加速的發(fā)展。
隨著更多Web服務(wù)應(yīng)用通過網(wǎng)絡(luò)交換XML信息,對于進(jìn)行高速處理、過濾和保護信息的安全來說,XML通信處理將不可避免地從應(yīng)用服務(wù)器軟件層面向硬件方向發(fā)展,密切相關(guān)的課題是在芯片上移植XML處理。VTD-XML正是這樣一種適合定制硬件實施的新型處理模型,它具有迷人的優(yōu)良特性,在XML處理領(lǐng)域有著非常廣闊的應(yīng)用前景。
[1][美]Sas Jacobs著.許勁松,楊波,周斌譯.XML基礎(chǔ)教程入門、DOM、Ajax與Flash.北京:人民郵電出版社,2007.
[2]OASIS.Web Services Resource Framework (WSRF)-Primer[EB/OL]http://docs.oasis-open.org/wsrf/wsrf-prime r-1.2-primer-cd-01.pdf.
[3]張志剛,XML加速器:優(yōu)化 XML應(yīng)用[J].中國計算機報,2004.2.9.
[4]Jimmy Zhang.Non-Extractive Parsing for XML [EB/OL]http://www.xml.com/pub/a/2004/05/19/Parsing.html.
[5]VTD-XML: The Future of XML Processing [EB/OL]http://vtd-xml.sourceforge.net/.
[6]Jimmy Zhang.XML on a chip [EB/OL]http://www.xml.com/lpt/a/2005/03/09/chip.html.