一、概述
在Web應用中,有些報表的生成可能需要資料庫花很長時間才能計算出來;有的網站提供天氣信息,它需要訪問遠端伺服器進行SOAP調用才能得到溫度資訊。這一切都屬於複雜資訊的例子。在Web頁面中加入過多的複雜資訊可能導致Web伺服器、資料庫伺服器負荷過重。 JSP程式碼區塊緩衝為開發者帶來了隨意地增加各種複雜資訊的自由。
JSP能夠在標記庫內封裝和運行複雜的Java程式碼,它使得JSP頁面文件更容易維護,使得非專業開發人員使用JSP頁面文件更加方便。現在已經有許多標記庫,它們或者是商業產品,或者是原始碼開放產品。但這些產品中的大多數都只是用標記庫的形式實現原本可以用一個簡單的Java Scriptlet實現的功能,很少有產品以某種創造性的方式使用定制標記,提供在出現JSP定制標記庫之前幾乎不可能實現的用法。
OSCache標記庫由OpenSymphony設計,它是一種開創性的JSP客製化標記應用,提供了在現有JSP頁面之內實現快速記憶體緩衝的功能。雖然已經有一些供應商在提供各種形式的快取產品,但是,它們都屬於特定供應商的產品。 OSCache能夠在任何JSP 1.1相容的伺服器上運行,它不僅能夠為所有使用者緩衝現有JSP程式碼區塊,而且能夠以使用者為單位進行緩衝。 OSCache也包含一些提高可伸縮性的高階特性,例如:緩衝到磁碟,可程式化的緩衝刷新,異常控制,等等。另外,正如OpenSymphony的其他產品,OSCache的程式碼也在一個開放原始碼授權協議之下免費發行。
本文以一個假想的拍賣網站設計流程為例,介紹OSCache的工作流程。這個假想的網路網站將包含:一個報告最近拍賣活動的管理頁面;一個功能完整、帶有各種宣傳訊息的主頁;一個特殊的導航條,它包含了用戶所有尚未成交的拍賣活動資訊。
二、管理頁面
拍賣網站包含一個管理報表,資料庫伺服器需要數秒時間才能建立這樣一個報表。報表產生時間長這一點很重要,因為我們可能讓多個管理員監視系統運作情況,同時又想避免管理員每次造訪時都重新產生這個報表。為了實現這一點,我們將把整個頁面封裝到一個應用程式級的緩衝標記之內,這個緩衝標記每隔1小時刷新。其他供應商提供的一些產品也具有類似的功能,只是OSCache比它們做得更好。
為簡單計,我們將不過度專注於格式問題。在寫管理頁面時,我們先把標記庫聲明加入到頁面:
<%@ taglib uri="cachetags" prefix="cache" %>
接下來我們要用cache標記來包圍整個頁面。 cache標記的預設緩衝時間是1小時。
<cache:cache> .... 複雜的管理報表.... </cache:cache>
現在管理頁面已經被緩衝。如果管理員在頁面產生後的一個小時之內再次造訪同一頁面,他看到的將是先前快取的頁面,不需要由資料庫伺服器再次產生這個報表。
三、主頁
拍賣網站的主頁顯示網站活動狀況,宣傳那些即將結束的拍賣活動。我們希望顯示正在進行的拍賣活動數量,目前登入使用者數量,在短期內就要結束的拍賣活動的清單,以及當前時間。這些資訊有著不同的時間精確度要求。網站上的拍賣活動通常持續數天,因此我們可以把緩衝有效拍賣活動數量的時間定為6個小時。使用者數量的變化顯然要頻繁一些,但這裡我們將把這個數值每次緩衝15分鐘。最後,我們希望頁面中顯示的當前時間總是精確的頁面存取時間。
在主頁中聲明標記庫之後,我們首先以不帶緩衝的方式直接輸出當前日期:
現在是:<%=new java.util.Date()%>
接下來,我們要顯示一個清單,列出那些將在短期內結束的拍賣活動:
<cache:cache> <ul> <% // 建構一個包含最近拍賣活動的Iterator Iterator auctions = .... while (auctions.hasMore()) { Auction auction = (Auction) auctions.next(); %><li><%=auction%></li%< } %> </ul> </cache:cache>
最後,我們希望顯示出正在進行的拍賣活動的數量,這個數字需要緩衝6小時。由於cache標記需要的是緩衝資料的秒數,我們把6小時轉換成21600秒:
<cache:cache time="21600"> <% //查詢資料庫得到拍賣活動總數int auctionCount = .... %>本網站正在進行的拍賣活動有<%=auctionCount%>個! </cache>
可以看到,我們只用少量的程式碼就建構出了一個有複雜緩衝系統的主頁。這個緩衝系統對頁面各部分分別進行緩衝,而且各個部分的緩衝時間完全符合它們各自的資訊變化頻繁程度。由於有了緩衝,現在我們可以在主頁中放入更多的內容;而在以前沒有緩衝的情況下,主頁中放入過多的內容會導致頁面訪問速度變慢,甚至可能為資料庫伺服器帶來過重的負載。
四、導航條
假設在規劃網站的時候,我們決定在左邊導航條的下方顯示購物車內容。我們將顯示用戶所拍賣的每一種商品的出價次數和當前報價,以及所有那些當前用戶出價最高的商品的清單。
我們利用會話層級的緩衝能力在導航條中建構上述功能。把下面的程式碼放入模板或包含文件,以便網站中的其他頁面引用這個導航條:
<cache:cache key="navbar" scope="session" time="300"> <% //提取並顯示當前的出價資訊%> </cache:cache>
在這裡我們引入了兩個重要的屬性,即key和scope。在本文前面的程式碼中,由於cache標記能夠自動為程式碼區塊建立唯一的key,所以我們不需要手動設定這個key屬性。但在這裡,我們想要從網站的其餘部分引用這個被緩衝的程式碼區塊,因此我們明確定義了該cache標記的key屬性。第二,scope屬性用來告訴cache標記目前程式碼區塊必須以使用者為單位緩衝,而不是為所有使用者緩衝一次。
在使用會話級緩衝時應該非常小心,應該很清楚:雖然我們可以讓複雜的導航條減少5倍或10倍的伺服器負載,但它將極大地增加每個會話所需的記憶體空間。在CPU能力方面增加可能的並髮用戶數量無疑很理想,但是,一旦在記憶體支援能力方面讓並髮用戶數量降低到了CPU的限制之下,這個方案就不再理想。
正如本文前面所提到的,我們希望從網站的其餘部分引用這個緩衝的程式碼區塊。這是因為,當一個用戶增加了一個供拍賣的商品、或出價競購其他用戶拍賣的商品時,我們希望刷新緩衝,使得導航條下一次被讀取時具有最新的內容。雖然這些數據可能因為其他用戶的活動而改變,但如果用戶在網站上執行某個動作後看到自己的清單仍未改變,他可能會感到非常困惑。
OSCache庫提供的flush標記能夠刷新緩衝內容。我們可以把下面的程式碼加入到處理使用者動作且可能影響這一區域的頁面之中:
<cache:flush key="navbar" scope="session" />
當使用者下次造訪它時,navbar緩衝區塊將被刷新。
至此為止,我們這個範例網站的建構工作已經完成且可以開始運作。下面我們就來看看OSCache的異常處理能力。即使緩衝的內容已經作廢,例如在緩衝區塊內出現了Java異常,OSCache標記庫仍舊允許我們用程式設計的方法顯示這些內容。有了這種異常控制功能,我們可以拆除資料庫伺服器和Web伺服器之間的連接,而網站仍能夠繼續運作。 JSP 1.2規格引入了TryCatchFinally接口,這個接口允許標記本身檢測和處理Java異常。因此,標記可以結合這個異常處理程式碼,讓JSP頁面更簡單、更有有條理。
OpenSymphony正在計劃實現其他的緩衝機制以及一個可管理性更好的主系統,它將使我們能夠對緩衝使用的RAM和磁碟空間進行管理。一旦有了這些功能,我們就能夠進一步提高網站的反應速度和可靠性。
【結束語】
OSCache能夠幫助我們建構出更豐富多彩、具有更高效能的網站。有了OSCache標記庫的幫助,現在我們能夠用它解決一些影響網站響應能力的問題,例如訪問量高峰期、資料庫伺服器負載過重等。