本文介紹如何提升 Java Web 服務性能,主要介紹了三種方法:一是采用 Web 服務的異步調用,二是引入 Web 服務批處理模式,三是壓縮 SOAP 消息。重點介紹在編程過程中如何使用異步 Web 服務以及異步調用和同步調用的差異點。本文還示范了如何在項目中使用以上三種方法,以及各種方法所適合的應用場景。
Java Web 服務簡介
Web 服務是一種面向服務架構的技術,通過標准的 Web 協議提供服務,目的是保證不同平台的應用服務可以互操作。Web 服務(Web Service)是基於 XML 和 HTTP 通訊的一種服務,其通信協議主要基於 SOAP,服務的描述通過 WSDL、UDDI 來發現和獲得服務的元數據。 這種建立在 XML 標准和 Internet 協議基礎上的 Web 服務是分布式計算的下一步發展方向,Web 服務為那些由不同資源構建的商業應用程序之間的通信和協作帶來了光明的前景,從而使它們可以彼此協作,而不受各自底層實現方案的影響。
JAX-RPC 1.0 是 Java 方面的 Web 服務的原始標准 , 但是由於 JAX-RPC 1.0 對 Web 服務功能的認識有一定的局限,於是 JAX-WS 2.0 應用而生。JAX-WS 2.0 開發工作的主要目標是對各項標准進行更新,成功實現了業界對 JAX-RPC 1.X 的各種期望。此外,JAX-WS 2.0 直接支持 XOP/MTOM,提高了系統附件傳送能力以及系統之間的互操作性。
實例剖析 Web 服務性能瓶頸
通過以上簡述不難體會到,Web 服務以其 XML + HTTP 的松耦合、平台無關的特性,集萬般寵愛於一身,必將成為未來數據共享的基礎。但與此同時我們也應當認識到世間完事萬物均有其矛盾的兩面性:有優點,必將存在缺點,Web 服務亦是如此。就像當初 JAVA 大行其道的時候性能成為其致命诟病一樣,Web 服務也同樣面臨性能問題,似乎“性能問題”天生就是“平台無關”揮之不去的冤家。但問題終歸要解決,實踐是檢驗和分析問題的唯一途徑,讓我們先來創建一個簡單的 Web 服務再來審視和分析隱含其中的性能問題。
創建服務
創建服務 Java Bean: 首先我們創建一個盡可能簡單的書店服務 Bean,服務的內容只有一個 qryBooksByAuthor,即根據作者 (Author) 查詢其名下的書籍 (List)。
圖 1. 書店服務 Bean(BookStoreSrvBean)
服務 Input- 作者 (Author) 的實體類 :
圖 2. 作者實體類 (Author)
服務出參 Output- 書籍 (Book) 列表的實體類:
圖 3. 書籍實體類 (Book)
至此我們的服務代碼已經完成,我們不在此討論此服務的業務合理性,創建此服務的目的只是舉一個盡可能簡單的實例以分析 web 服務的性能。
下面的任務就是開發 Web 服務了,手工編寫及發布符合規范的 Web 服務過程極為繁瑣,在此使用 IBM 的 Rational Software Architect(後面簡稱 RSA)來進行 Web 服務的服務器端以及客戶端的開發。
發布 Web 服務
創建動態 Web 項目 : 發布 Web 服務的前提當然需要一個 J2EE 的 Web 項目,打開 RSA->File->New->Dynamic Web Project, 項目名稱為 testWebService, 其余選項根據需要進行選擇 ( 注意需要選擇加入 Web 項目到 EAR)。創建好的 Web 項目和 EAR 項目效果如下 :
圖 4. Web 項目以及應用項目的結構
創建 Web 服務: 選中導入的 com.ibm.test.ws.srv.BookStoreSrvBean,右鍵 New->Other->Web Service 來創建並發布 Web 服務。創建的時候選擇常用的 JAX-WS 標准 , 並選擇生成 WSDL 文件。由於 Web 服務的創建不是本文重點,此部分內容暫且省略。服務創建完成之後就可以發布到上一步建好的 Web 項目中了。
創建客戶端
使用 RSA,客戶端的創建工作將會非常簡單:右鍵點擊上面生成的 WSDL 文件 ->Web Services->Generate Client
圖 5. 創建客戶端界面
在此界面,根據實際情況選擇 server,JAX-WS 標准以及 Client 代碼的目標項目,然後點擊下一步。
圖 6. 輸入客戶端信息
此界面暫時使用默認配置,某些特殊選項將在後面章節進行描述。
客戶端調用
由於 JAX-WS 規范大部分的 stub 調用代碼是實時生成的,我們只需要修改客戶端 WSDL 的 port 就可以用以下代碼進行 Web 服務的調用。這裡修改 WSDL 端口的目的是讓客戶端調用 RSA 提供的 TCP/IP Monitor 的虛擬端口,這樣我們就可以很輕易地看到 Web 服務實際的調用以及返回的 SOAP 消息了。
客戶端調用代碼如下 :
圖 7. 客戶端調用代碼
使用 TCP/IP Monitor 看到的 SOAP 消息如下 :
圖 8. Web 服務調用產生的 SOAP 消息
Java Web 服務性能分析
從以上實例我們可以看到,Web 服務的調用與傳統的 RPC 還是有較大差異的。最大的特點是調用雙方使用 XML 格式的 SOAP 規范消息進行傳輸,這樣以文本進行傳輸的好處是拋棄了私有協議,無論調用雙方是何種平台,只要能夠構造以及解析 XML 文本,並且存在雙方都支持的傳輸協議,那麼調用就成為了可能。而 XML 的日益規范以及 HTTP 協議的普及更是給這兩個必要條件提供了堅強的後盾,Web 服務成為未來通用的服務提供標准已是不爭的事實。
但是相信使用過 Web 服務的人都曾經經受過其性能不佳的窘境,原因為何我們結合剛才的實例可以分析出以下幾點:
● SOAP 文本消息轉化導致效率低下
從剛才的 TCP/IP Monitor 監測到的 request 以及 response 的消息我們可以看到,在發送消息時,我們傳入了 Author 對象,在實際的調用發生時,這個 Author 對象會被轉化成 XML 格式的 SOAP 消息,此消息在到達 Server 端會被解析並重新構造成 Server 端的 Author 對象。Response 也是同理,Books List 也會經歷 XML 序列化和反序列化的過程。最糟糕的是,這種過程會在每一次調用的時候都會發生,這種構造以及解析的過程都會極大地消耗 CPU,造成資源的消耗。
●SOAP 文本消息傳輸導致傳輸內容膨脹
以 request 參數 Author 為例,必要的信息僅僅是”Bruce Eckel”這幾個字節,但轉化成 XML 消息後,可以從 SOAP 消息看到,多了很多 SOAP 規范的標簽,這些信息會導致需要傳輸的內容急劇增大,幾個字節很可能會變成幾千字節。當調用頻度和參數內容增多的時候,這種傳輸內容的膨脹將不是一個可以忽略的影響,它不但會吃掉網絡的帶寬,還會給 Server 的數據吞吐能力造成負擔,後果可想而知。
●同步阻塞調用在某些情況下導致性能低下
同步阻塞調用是指客戶端在調用 Web 服務發送 request 後一直處於阻塞狀態,客戶端線程就會掛起,一直處於等待狀態,不能進行其他任務的處理。這樣就會造成線程的浪費,如果相應線程占用了一些資源,也不能夠及時釋放。
這個問題在純客戶端訪問 Server 端的情況下並不明顯,但如果是兩個 Server 端之間進行 Web 服務調用的話,阻塞模式就會成為調用 Server 端的性能瓶頸。
Web 服務性能優化實踐
使用異步方式調用 web 服務
先需要強調一點的是,這裡的異步方式指的是客戶端的異步,無論客戶端是同步還是異步,都對服務端沒有任何影響。我們期望的理想結果是:當客戶端發送了調用請求後不必阻塞等待 server 端的返回結果。最新的 JAX-WS 標准中增加了這一異步調用的特性,更好的消息是,RSA 工具中也對 JAX-WS 的這一特性進行了支持,這樣就極大地方便了我們進行異步調用客戶端的創建。
其實講客戶端配置為異步模式極其簡單,只要在 RSA 生成 Client 端代碼時將‘ Enable asynchronous invocation for generated client ’ 選中即可 , 如下圖 :
圖 9. 異步客戶端創建選項
這樣在生成的客戶端的 BookStoreSrvBeanService 中就會多了 qryBooksByAuthorAsync 的異步方法。既