利用OSB (Oracle Service Bus)的Content Streaming處理大消息
?
?? 最近發現有人用OSB (Oracle Service Bus,即原BEA的AquaLogic Service Bus的后續版),傳送消息的文本大小 平均接近200K,最大有10M。這種消息大小看來不是常規的一些業務字段,而是較大的業務報文。這樣大的消息,又是XML的,恐怕對OSB的性能有影響。
?
??? 這是你在OSB的代理服務里面使用了Message Flow,里面可能用到你的body的一些子元素的值做判斷,然后調用什么服務云云,這些事情的背后的一個前提是你的報文XML是經過解析后成一個JavaBean的,否則其他地方何以讀取其中的子元素(用XPath取值或者XQuery等等)。要命的是,如果XML報文很大,對內存的占用就也很大,而且你的系統肯定不是單用戶單請求的吧。
?
??? 其實OSB提供了一種解決方法,即是采用一種稱為Content Streaming的方式來支持大消息的傳輸,要深入理解這個功能并不容易,作為第一步,你可以理解成body不XML解析,因此省掉了解析的時間,也省掉了內存上的大消耗。而方法你只需要在Proxy Service上設置Enable Content Streaming即可(其實選項也有幾個variation,后面再說),見下圖。
??? 除此以外,有幾個要點,是應當知道的。
??? 第一點必須知道的重要概念,就是當你為你的Proxy Service打開或者說Enable了Streaming后,你不可以再用修改body的那些Action,如Replace/Delete/Rename。原因不言自明,因為沒有做過Parse,也就沒有代表XML內容的相應的JavaBean,所以無法修改。
??? 第二點也很重要也應該知道,SOAP的Header還是會照常被Parse的,你可以讀取或者修改header對象。因此,如果你想做所謂Content-Based-Routing的話,你更應當把這類Content放到Header中。
??? 第三點就是,如果實在必要,其實你還是可以讀取body的一部分內容,但是這里要想不影響性能,就有不少要注意的東西和技巧了,否則,就跟沒有用Streaming是一樣的了,這里的內容分以下幾點補充說明(很重要,這是理解streaming的關鍵):
??? - 讀取部分內容在OSB的術語上叫做Partial Parsing,即部分解析,只解析XML報文中的部分內容(你想要讀的那部分)。
??? - 可以用Assign這個Action來讀取一個子元素,但是千萬要注意你的XPath的寫法了。假設你的body里面有子元素myElement,其下再有子元素mySub,那么你可能會用$body/myElement/mySub來讀取你的子元素的值,但其實這個寫法會導致整體XML被解析而不是Partial Parsing。等我給出正確的寫法你就明白為什么了,正確的寫法是$body/myElement[1]/mySub[1],它表示找到第一個myElement元素,然后讀取它底下的第一個mySub子元素。或許你還以為這兩者沒什么區別,但在這里區別可大了。有了[1](英文術語叫做indexing)除了表示第一個之外,還表示就這一個(后面第二個什么的不要了);但是沒有[1]就表示“所有”的這個名稱的元素,也就表示了找到第一個還繼續往后面找,直到全部的都找出來,換取話說,$body/myElement/mySub邏輯上可能返回多個mySub元素的集合;說到這里,應該很明了了吧。你或許還覺得,不怕,我的XML報文肯定只有一個myElement/mySub。沒錯,你沒錯,但是OSB并不知道,只要你沒有寫明[1],OSB就認為任務還沒有完成,還要繼續工作,繼續找到報文最末段為止。
??? - 上面這點很是費口舌,同時你或許已猜出,OSB是從body的開頭就開始進行Parse,直到找到(找齊)你想要的結果為止才結束Parsing。所以,被Parse的那段報文就是body的開頭到你的目標元素的這一段。因此,一般來說,你要讀取的內容應當在body里面是靠前的部分,這樣才可以盡可能減少不必要的Parsing。如果你要找的元素是出現在最后的話,那么就跟沒有streaming沒什么差別了。
??? - 同時,應當減少對body的讀取次數,如果可以,你盡量重復利用第一次讀取的結果,如:
??? Assign "$body/myElement[1]/mySub[1]" to "mysub"
??? Assign "$mysub/ele1" to "value1"
??? Assign "$mysub/ele2" to "value2"
??? 以上的寫法對body的讀取只有一次,但如果你讀取ele1時寫成是Assign "$body/myElement[1]/mySub[1]/ele1" to "value1",那么你就兩次使用body了,這是不建議的。
?
??? 現在說一說設置Streaming時的選項吧,因為Reliability的緣故,OSB還是會把body的內容用一種串行化(Serialized,而不是XML對應的JavaBean,那個叫Materialized)的形式存放起來,選擇Memory則是在消耗內存,但沒有IO;選擇Disk則是消耗IO,不占用內存。而選擇Enable Compression則是消耗CPU,較少內存或者Disk的存量。
?
??? 最后,值得注意的是,消息體越大,使用streaming的價值就越大,反之亦然。所以,不要盲目在小消息體上使用Streaming。
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
