你的JEE應用是不是運行的很慢?它們能不能承受住不斷上升的訪問量?本文講述了開發高性能高彈性的JSP頁面和Servlet的性能優化技術其意思是建立盡可能快的並能適應數量增長的用戶及其請求在本文中我將帶領你學習已經實踐和得到證實的性能調整技術它將大大地提高你的servlet和jsp頁面的性能進而提升JEE的性能這些技術的部分用於開發階段例如設計和編碼階段另一部分技術則與配置相關
技術在HttpServlet init()方法中緩存數據
服務器會在創建servlet實例之後和servlet處理任何請求之前調用servlet的init()方法該方法在servlet的生命周期中僅調用一次為了提高性能在init()中緩存靜態數據或完成要在初始化期間完成的代價昂貴的操作例如一個最佳實踐是使用實現了javaxsqlDataSource接口的JDBC連接池DataSource從JNDI樹中獲得每調用一次SQL就要使用JNDI查找DataSource是非常昂貴的工作而且嚴重影響了應用的性能Servlet的init()方法可以用於獲取DataSource並緩存它以便之後的重用
public class ControllerServlet extends HttpServlet
{
private javaxsqlDataSource testDS = null;
public void init(ServletConfig config) throws ServletException
{
superinit(config);
Context ctx = null;
try
{
ctx = new InitialContext();
testDS = (javaxsqlDataSource)ctxlookup("jdbc/testDS");
}
catch(NamingException ne)
{
neprintStackTrace();
}
catch(Exception e)
{
eprintStackTrace();
}
}
public javaxsqlDataSource getTestDS()
{
return testDS;
}
}
技術禁用servlet和Jsp的自動裝載功能
當每次修改了Servlet/JSP之後你將不得不重新啟動服務器由於自動裝載功能減少開發時間該功能被認為在開發階段是非常有用的但是它在運行階段是非常昂貴的servlet/JSP由於不必要的裝載增加類裝載器的負擔而造成很差的性能同樣這會使你的應用由於已被某種類裝載器裝載的類不能和當前類裝載器裝載的類不能相互協作而出現奇怪的沖突現象因此在運行環境中為了得到更好的性能關閉servlet/JSP的自動裝載功能
技術控制HttpSession
許多應用需要一系列客戶端的請求因此他們能互相相關聯由於HTTP協議是無狀態的所以基於Web的應用需要負責維護這樣一個叫做session的狀態為了支持必須維護狀態的應用Java servlet技術提供了管理session和允許多種機制實現session的APIHttpSession對象扮演了session但是使用它需要成本無論何時HttpSession被使用和重寫它都由servlet讀取你可以通過使用下面的技術來提高性能
在JSP頁面中不要創建默認的HttpSession:默認情況下JSP頁面創建HttpSession如果你在JSP頁面中不用HttpSession為了節省性能開銷使用下邊的頁面指令可以避免自動創建HttpSession對象
< %@ page session="false"%>
不要將大的對象圖存儲在HttpSession中如果你將數據當作一個大的對象圖存儲在HttpSession中應用服務器每次將不得不處理整個HttpSession對象這將迫使Java序列化和增加計算開銷由於序列化的開銷隨著存儲在HttpSession對象中數據對象的增大系統的吞吐量將會下降
用完後釋放HttpSession當不在使用HttpSession時使用HttpSessioninvalidate()方法使sesion失效
設置超時值一個servlet引擎有一個默認的超時值如果你不刪除session或者一直把session用到它超時的時候servlet引擎將把session從內存中刪除由於在內存和垃圾收集上的開銷session的超時值越大它對系統彈性和性能的影響也越大試著將session的超時值設置的盡可能低
技術使用gzip壓縮
壓縮是刪除冗余信息的作法用盡可能小的空間描述你的信息使用gzip(GNU zip)壓縮文檔能有效地減少下載HTML文件的時間你的信息量越小它們被送出的速度越快因此如果你壓縮了由你web應用產生的內容它到達用戶並顯示在用戶屏幕上的速度就越快不是任何浏覽器都支持gzip壓縮的但檢查一個浏覽器是否支持它並發送gzip壓縮內容到浏覽器是很容易的事情下邊的代碼段說明了如何發送壓縮的內容
public void doGet(HttpServletRequest request HttpServletResponse response)
throws IOException ServletException
{
OutputStream out = null
// Check the AcceptingEncoding header from the HTTP request
// If the header includes gzip choose GZIP
// If the header includes compress choose ZIP
// Otherwise choose no compression
String encoding = requestgetHeader("AcceptEncoding");
if (encoding != null && encodingindexOf("gzip") != )
{
responsesetHeader("ContentEncoding" "gzip");
out = new GZIPOutputStream(responsegetOutputStream());
}
else if (encoding != null && encodingindexOf("compress") != )
{
responsesetHeader("ContentEncoding" "compress");
out = new ZIPOutputStream(responsegetOutputStream());
}
else
{
out = responsegetOutputStream();
}
}
技術不要使用SingleThreadModel
SingleThreadModel保證servlet一次僅處理一個請求如果一個servlet實現了這個接口servlet引擎將為每個新的請求創建一個單獨的servlet實例這將引起大量的系統開銷如果你需要解決線程安全問題請使用其他的辦法替代這個接口SingleThreadModel在Servlet 中是不再提倡使用
技術使用線程池
servlet引擎為每個請求創建一個單獨的線程將該線程指派給service()方法然後在service()方法執行完後刪除該線程默認情況下servlet引擎可能為每個請求創建一個新的線程由於創建和刪除線程的開銷是很昂貴的於是這種默認行為降低了系統的性能我們可以使用線程池來提高性能根據預期的並發用戶數量配置一個線程池設置好線程池裡的線程數量的最小和最大值以及增長的最小和最大值起初servlet引擎創建一個線程數與配置中的最小線程數量相等的線程池然後servlet引擎把池中的一個線程指派給一個請求而不是每次都創建新的線程完成操作之後servlet引擎把線程放回到線程池中使用線程池性能可以顯著地提高如果需要根據線程的最大數和增長數可以創建更多的線程
技術選擇正確的包括機制
在JSP頁面中有兩中方式可以包括文件包括指令(< %@ include file="testjsp" %>)和包括動作(< jsp:include page="testjsp" flush="true" />)包括指令在編譯階段包括一個指定文件的內容例如當一個頁面編譯成一個servlet時包括動作是指在請求階段包括文件內容例如當一個用戶請求一個頁面時包括指令要比包括動作快些因此除非被包括的文件經常變動否則使用包括指令將會獲得更好的性能
技術在useBean動作中使用合適的范圍
使用JSP頁面最強大方式之一是和JavaBean組件協同工作JavaBean使用< jsp:useBean>標簽可以嵌入到JSP頁面中語法如下
< jsp:useBean id="name" scope="page|request|session|application" class=
"packageclassName" type="typeName">
< /jsp:useBean>
scope屬性說明了bean的可見范圍scope屬性的默認值是page你應該根據你應用的需求選擇正確的范圍否則它將影響應用的性能
例如如果你需要一個專用於某些請求的對象但是你把范圍設置成了session那麼那個對象將在請求結束之後還保留在內存中它將一直保留在內存中除非你明確地把它從內存中刪除使session無效或session超時如果你沒有選擇正確的范圍屬性由於內存和垃圾收集的開銷將會影響性能因此為對象設置合適的范圍並在用完它們之後立即刪除
From:http://tw.wingwit.com/Article/program/Java/JSP/201311/20349.html