Servlet和JSP 效能調整技術

來源:互聯網
上載者:User
js|servlet|效能    概述

在本文中, Rahul Chaudhary將描述效能調整技術 (PTT performance-tuning techniques) 的使用,來提升servlets 和JSP 的效能,以此來提升你的J2EE應用的效能。筆者假設讀者具有基礎的servlets 和JSPs知識。

你的J2EE應用程式運行緩慢嗎?它們可以滿足足夠的壓力嗎?本文將會描述如何在開發高效能的應用和JSP以及servlets中使用效能調整技術 (PTT performance-tuning techniques)。使用這些技術可以構建更加快速、穩健的系統,以滿足更多使用者或者更多請求的需要。在本文中,我將會帶你進行實際的實踐,實驗如何調整效能提升你的servlets 和 JSP 頁面緩慢的效能,最終以提升你的J2EE應用的效能。其中一部分技術使用在開發過程階段,也就是說,適應於在你進行系統設計或者編寫代碼的時候。另外一些則是和配置相關技術。

調整方法1:使用 HttpServlet init()方法快取資料

應用伺服器在servlet開始構造的時候,接受處理任何請求之前調用servlet的init()方法。在servlet的生命週期中僅僅調用一次。Init()方法通過緩衝待用資料或者完成佔用大量資源的操作,用來在初始化的過程中提高效能。

舉例說明,通過使用jdbc串連池是一個最好的實踐,在調用javax.sql.DataSource介面的時候。依靠通過JNDI(java命名和服務介面)樹獲得DataSource.如果在每一次SQL調用時候都進行JNDI尋找DataSource ,將會嚴重的影響應用服務的應能。Servlet的init()方法將用來取得DataSource,並且將其進行緩衝以備以後使用。

public class ControllerServlet extends HttpServlet

{

private javax.sql.DataSource testDS = null;

public void init(ServletConfig config) throws ServletException

{

super.init(config);

Context ctx = null;

try

{

ctx = new InitialContext();

testDS = (javax.sql.DataSource)ctx.lookup("jdbc/testDS");

}

catch(NamingException ne)

{

ne.printStackTrace();

}

catch(Exception e)

{

e.printStackTrace();

}

}

public javax.sql.DataSource getTestDS()

{

return testDS;

}

……

……

}

調整方法2:禁止servlet和jsp的自動重載

為了節約開發時間,在開發階段Servlet/JSP容器提供自動重載功能,方便你在修改Servlet/JSP後不用重新啟動服務。可是,在生產環境下面,卻是佔用大量開銷,因為進行了沒有必要的重新載入的操作,所以帶來了很懷的效能影響。同時,在部分類載入,部分為載入的時候也可能帶來各種奇怪的衝突。因此在J2EE的生產環境下關閉自動載入功能可以得到更好的效能。

一、在一個大型的J2EE項目中進行大量壓力測試下,在開發模式下莫名其妙的發生錯誤,部分請求任務失敗,就是因為載入類造成的系統衝突。

二、在另外一個大型的J2EE項目實際應用過程中,突發的大量使用者讓足以滿足使用者的系統處於癱瘓邊緣,經過了系統、資料庫、應用伺服器等等調整後,終沒有解決問題。最後不得不排除人員去現場解決,最後發現問題竟是這個原因。這個事件僅僅發生在前天。

調整方法3:控制HttpSession

許多應用服務需要一系列的客戶請求,這些請求之間又相互依存。因為http協議是無狀態的,所以基於web的應用系統必須使用session技術來維持串連。為了實現應用服務進行狀態管理,java servlet技術提供了一套API,通過使用HttpSession對象進行會話管理,但是在使用這個功能的同時,不管servlet進行任何請求,HttpSession對象都要進行讀寫,伺服器也承擔了響應的系統開銷。你可以使用下列方法提升效能。

在預設情況下,不要在jsp頁面中建立HttpSessions對象,jsp頁面預設會自動建立HttpSessions,如果在你的jsp頁面中不需要HttpSessions,為了節省一些效能,使用下面的頁面指令避免自動建立HttpSessions對象。

<;%@ page session="false"%>

不要儲存大型物件到HttpSession:如果你儲存大型物件資料到HttpSession中,應用伺服器不得不在每一次請求中處理整個的HttpSession,這將會強迫使用java的序列化操作,佔用大量系統資源。應用服務的效能將會因為java的序列化操作而減少。

在結束時候釋放HttpSessions對象:在它們不在需要的時候使用HttpSession.invalidate()方法消除sessions.

設定session的逾時值:servlet有一個預設的逾時值。如果你在這個時間裡面,你既沒有移除它,也沒有使用它(進行任何服務要求),servlet服務將會自動將其銷毀。因為對記憶體和垃圾的回收處理,因此,逾時值越大,對伺服器的效能影響越大。所以,儘可能的保持session的逾時值最小。

調整方法4:使用gzip壓縮

壓縮是一個去處庸餘資訊的操作,以便可以使用最小的空間儲存。使用gzip(GNU zip)壓縮內容可以顯著的減少下載HTML檔案的時間。資訊內容越小,傳送的速度越快。因此,如果在產生web應用的時候壓縮內容,就可以更快的傳送、顯示在使用者的螢幕上面。由於不是每一個瀏覽器都支援gzip壓縮功能,所以你必須簡單的檢查瀏覽器是否支援。

下面代碼是示範如何發送壓縮內容的例子:

public void doGet(HttpServletRequest request, HttpServletResponse response)

throws IOException, ServletException

{

OutputStream out = null

// Check the Accepting-Encoding 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 = request.getHeader("Accept-Encoding");

if (encoding != null && encoding.indexOf("gzip") != -1)

{

response.setHeader("Content-Encoding" , "gzip");

out = new GZIPOutputStream(response.getOutputStream());

}

else if (encoding != null && encoding.indexOf("compress") != -1)

{

response.setHeader("Content-Encoding" , "compress");

out = new ZIPOutputStream(response.getOutputStream());

}

else

{

out = response.getOutputStream();

}

……

……

}

調整方法5:不要使用SingleThreadModel

SingleThreadModel介面確保servlet在同一時間只接受一個請求。如果servlet實現這個介面,servlet將會為每一個新的請求建立隔離的servelet執行個體,這將造成很大的系統開銷。如果你需要處理安全執行緒問題,可以使用其他方法代替這種方法。在servlet2.4中SingleThreadModel介面已經被反對使用。

調整方法6:使用線程池

Servlet引擎為每一個請求建立一個隔離的線程,分配這個線程給service()方法,在它執行完後移除這個線程。預設情況下,servlet引擎為每一個請求建立新的線程。因為建立和消除線程是需要系統開銷的,這種行為將會引起效能問題。可以通過使用線程池來提升效能。依據所期望的並發使用者數量,配置線程池的最大、最小、以及增加數量。在服務啟動的時候,servlet引擎使用最小的線程數量建立一個線程池。然後servlet引擎會分配線程給每一個請求,替換原來的建立新的線程,在處理完成後把線程返回給線程池。使用線程池,效能會有一個顯著的提升。如果需要,根據線程的最大和增加數量,更多的線程會被建立,添加到池中以供更多的請求使用。

調整方法7:選擇正確的包含機制

在jsp中有兩種方法使用包含檔案:包含指令(<;%@ include file="test.jsp" %>) 和包含動作 (<;jsp:include page="test.jsp" flush="true" />)。包含指令在轉換的過程中包含檔案內容;也就是說,在一個頁面轉換成一個servlet的時候。包含動作在請求處理的階段包含檔案內容;也就是說,在一個使用者請求頁面的時候。包含指令快於包含動作。因此,除非被包含的內容經常變化,應該使用包含指令提升效能。

調整方法8:選擇正確的範圍在使用useBean動作

Jsp頁面的一個強大功能就是在jsp中互動使用JavaBeans組件。通過使用<;jsp:useBean>動作標籤,JavaBeans可以被直接的嵌入jsp頁面中。文法如下:

<;jsp:useBean id="name" scope="page|request|session|application" class=

"package.className" type="typeName">

<;/jsp:useBean>

範圍屬性指定了bean的作用範圍。它的預設值是page.你可以根據你的系統要求選擇正確的範圍。否則它會影響到應用系統的效能。

舉例說明,如果你需要一個對象僅僅作為請求使用,但是你的範圍設定為session,在你完成請求後,這個對象將依然會留在記憶體中。直到你明確的清楚它為止,通過銷毀session,或者session自動逾時。假如你沒有選擇正確的範圍,它同樣也會影響效能因為過度的記憶體和垃圾收集。因此,需要正確的設定對象的範圍,同時當你使用完成之後,也應該立即去除它們。

其他方法:

避免字串相加:使用 + 操作會產生很多臨時對象,因為String是不可變化(immutable)的對象。越多的 + 操作,越多的臨時對象會被建立,造成很大的系統開銷。使用StringBuffer替換 + 操作,當你需要字串相加的時候。

避免使用System.out.println:System.out.println是同步處理的在disk i/o操作中,並且會嚴重的影響效能。因此最大可能的要避免使用System.out.println.儘管存在強大的調試工具,有時候為了跟蹤目的、錯誤處理、偵錯工具,還是使用System.out.println.你應該配置System.out.println僅僅在開發和調試情況下使用。使用一個靜態final boolean變數,在生產模式下,配置成false,避免System.out.println的使用。

ServletOutputStream比較PrintWriter:使用PrintWriter會佔用一些系統開銷,因為它是為處理字元流的輸出輸出功能。因此PrintWriter應該使用在確保有字元集轉換的環境中。換句話說,在你知道servlet返回的僅僅是位元據時候,應該使用ServletOutputStream,這樣你可以消除字元轉換開銷,當servlet容器不用處理字元集轉換的時候。

總結

本文的目的是通過一些實踐操作,使用效能調整技術,通過提升servlets和jsp頁面的效能,進而提升J2EE應用系統的效能。下一次將會涉及效能調整關於EJB (Enterprise JavaBeans), JMS (Java Message Service), and JDBC (Java Database Connectivity)。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.