JWorld@TW the best professional Java site in Taiwan
      註冊 | 登入 | 全文檢索 | 排行榜  

» JWorld@TW » Servlet/JSP 討論區  

按列印兼容模式列印這個話題 列印話題    把這個話題寄給朋友 寄給朋友   
reply to topicthreaded modego to previous topicgo to next topic
己加入精華區
by browser at 2005-12-16 16:08
本主題所含的標籤
無標籤
作者 JSP & Servlets 效能調校提示 [精華]
je





發文: 112
積分: 2
於 2005-12-16 15:34 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
本文譯自:
Six Steps to Faster J2EE Apps: Performance Tuning with JSP and Servlets
http://javaboutique.internet.com/tutorials/tuning/

----------------------------------------------------------------
本文:
 你的 J2EE 應用程式是否能承受同時大量的客戶端請求?抑或它已經運作得越來越慢,且回應時間越拖越久了呢?這類的效能瓶頸可能源自多重原因。以下提供六項簡單的提示以加速您的應用程式,您可將其套用在專案的設計或開發階段。
 

提示一 採用正確的 Include 機制

 有兩種方法可以 include 檔案在 JSP 中:

1. Include directive(<%@include file="test.jsp" %>):
  在編譯階段,當頁面被轉換成 Servlet 時,檔案(test.jsp)的內容就會被讀進來。(譯註:為靜態載入,只能包含檔案但不能包含 URL 或接參數)

2. Include action(<jsp:include page="test.jsp" flush="true" />):
  在執行時期,等到 user 的 request 產生時才讀取檔案內容。(譯註:亦即可動態載入,並自行判斷是否也將 test.jsp 編譯執行)

 Include directive 的速度會比 Include action 快,因為包含的過程是靜態的,被包含的頁面在執行過程不需要被編譯,也因此不用在伺服端做處理(除了將該頁面傳回客戶端時)。如果你的檔案不常更動內容,或其並非動態頁面,使用 Include directive 將可獲得一些效能增益。
 

提示二 在 useBean Action 中使用正確的 Scope

 JSP 可將現存的程式碼放在 JavaBeans 之中以便重複使用,將其嵌入頁面的語法如下:
1
<jsp:useBean id="name" scope="request|page|session|application" class="package.className" type="typeName" />

重點在 scope 屬性,若未指定的話預設值為 page,而選擇正確的 scope 將有助於運作效能。舉例而言,如果你只是為了一次特定的 request 而使用 bean,但卻將 scope 設為 session,即便該 request 生命週期已結束,但物件仍會一直存留在記憶體中。除非你明確地用 invalidate() 方法移除掉 session,或等到 session 的生命週期完結(譯註:1800秒)。

(譯註:亦可呼叫 removeAttribute() 移除 session 中的屬性,在此例中即指 JavaBeans。或是呼叫 sexMaxInactiveInterval(),以設定 session 在一定的時間內沒有作用就過期)
 

提示三 用 HttpServlet 的 init() 方法將資料快取

 在 Servlet 的 instance 被建立後,以及任何客戶端 requests 被處理之前,Servlet 的 init() 方法會被伺服器呼叫,且其在 Servlet 的生命週期中只會被呼叫一次。因此,若把一些初始化、或較消耗系統資源的動作放在 init() 方法中來處理,將可得到較佳之運作效能。比方說 Connection pooling 就很適合放在此一方法中,我們可以建立與設定需要的 connections 數目以便之後重複使用。

(譯註 1:相對於 Servlet 第一次啟動時會自動被執行的 init(),亦有 Servlet 被 destroy 時會自動被執行的 destroy() 方法)
(譯註 2:JSP 另有功能類似的 jspInit()、jspDestroy(),可將一些希望一定會被執行,但只被執行一次的程式碼放置其中)
(譯註 3:下方程式碼為該文所附,以 JNDI 查 DataSource 的程式碼)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class TaskServlet extends HttpServlet {
 
  private javax.sql.DataSource dataSource = null;
 
  public void init(ServletConfig config) throws ServletException {
    super.init(config); 
    Context context = null;
    try { 
      context = new InitialContext();
      dataSource = (javax.sql.DataSource)context.lookup("jdbc/dataSource");
    } catch(NamingException namingException) {
      namingException.printStackTrace(); 
    } catch(Exception exception) {
      exception.printStackTrace();
    }
  }
 
  public java.sql.Connection getConnection() {
    // 從 dataSource 回傳 connection
  }
 
  // 其它功能的程式碼
}

 

提示四 停用 JSP & Servlets 的 Auto-Reloading 功能

 Auto-reloading 功能,省去了我們每次修改 JSP & Servlet 後必須重新啟動伺服器的麻煩。但是由於該功能會包含額外的動作和非必要的 loading,以致於對 Classloader 和系統效能造成影響,甚至於可能造成不可預期的 class 衝突。例如較早的 Classloader 所載入的 class,可能無法和目前 Classloader 載入的 class 協同運作。因此建議在系統的開發階段以及系統上線後,都將該功能關閉。

(譯註:Auto-Reloading 應該是指 Container 中 server.xml 所設定的 <Context …… reloadable="true">,在一些 Web Container 例如 Tomcat 的說明檔中,{%CATALINA_HOME%}\webapps\tomcat-docs\config\context.html,也有提到該功能有助於開發階段的測試工作,但因會造成系統負擔,因此不建議在部署後仍使用,因此該功能預設為關閉的。但仍有所謂的 Manager web app 功能,以便系統上線後仍舊能依需要而觸發 reloading 動作,詳情請參閱書籍或您 Web Container 的說明檔。而在本討論區中也有相關論述:
http://www.javaworld.com.tw/jute/post/view?bid=9&id=56779&sty=3&keywords=reloading
有人認為在系統開發階段應開啟該項功能以便測試,但正式上線後則應關閉以免影響運作效能)
 

提示五 管理 Session

 大部份應用程式都需要 Session 來維持客戶端 request 的連串運作,Servlet 也提供了相關 API 以作 Session 的管理。但是使用 HttpSession 物件來管理 Sessions,多少會消耗一些應用程式的效能。

 所有的 JSP 頁面預設都會建立一個 HttpSession 的 instance,以幫助我們呼叫和決定是否要使用。然而當我們不需要該功能時,就應該避免去建立它(譯註:Session 功能預設是開啟的),並以下列的程式碼來要求伺服器不要建立 Session:
1
<%@ page session="false"%>

 另一個應避免使用 HttpSession 的原因,是因為只要有任一個 request 產生,HttpSession 物件都會被運作處理。要是我們將大型物件儲存於其中,將會造成效能上的瓶頸。如果我們非用 HttpSession 不可,至少應該避免將大型物件存在裡面。

 事實上,讓 Session 持續一直運作是不明智的,將其生命週期依應用程式需求設定得較短些,將有助於整體的運作效能。而且有一點永遠要記得的,就是當不再需要使用 Session 時,應該用 HttpSession 的 invalidate() 方法將其移除,以便從記憶體中釋放掉。
 

提示六 使用 gzip 壓縮

 壓縮功能可讓資料體積縮小,其規格有很多種,這裡所要介紹的為 gzip(GNU zip)。目前大部份的瀏覽器都支援 gzip,將資料以該規格先壓縮過將可加快傳送速度。以下為範例程式碼:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public void doGet(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) 
                           throws IOException, ServletException {
 
  OutputStream out = null;
 
  // 檢查客戶端瀏覽器是否支援該規格
  // 我們可以用 HTTP request 的 Accepting-Encoding header 來做檢查
  // 如果 header(表頭)包含 gzip,就選擇用 GZIP,否則不要壓縮
 
  String encoding = httpServletRequest.getHeader("Accept-Encoding"); 
 
  if (encoding != null && encoding.indexOf("gzip") != -1) {        // 若瀏覽器支援壓縮,也支援 gzip
    httpServletResponse.setHeader("Content-Encoding" , "gzip");
    out = new GZIPOutputStream(httpServletResponse.getOutputStream());
  } else if (encoding != null && encoding.indexOf("compress") != -1) { // 若瀏覽器支援壓縮,但不支援 gzip
    httpServletResponse.setHeader("Content-Encoding" , "compress");
    out = new ZIPOutputStream(httpServletResponse.getOutputStream());
  } else {
    out = httpServletResponse.getOutputStream();
  }
 
  // 其它功能的程式碼
}

(譯註 :本功能譯者自己未曾試過,有興趣者可自行測試看看)
 

譯者的結論(原文無結論):

 由於 JSP 中資料的傳遞皆為字串,且 JSP 擁有廣大的類別函式庫支援,因此亦需更注意各種型別之間轉換所消耗掉的效能,包括基本型別、字串、物件、Wrapper Class 之間的轉換皆然。而不論是自動轉型、強制轉型(Casting)、用 Java 內建的 method 轉型,或 Java 5.0 提供的 Autoboxing/Unboxing,小弟我認為仍都應儘可能減少使用,因為只要有轉型的動作,或多或少都會消耗效能和記憶體。此外,要扔到資料庫中去查詢的 SQL 敘述句,亦應注意大量字串串接對效能的影響,雖然 .NET 和 Java 的 StringBuilder 和 StringBuffer 類別的物件,無法直接用在 SQL 敘述句中去資料庫裡撈資料,但仍有折衷的做法,亦即先用 StringBuffer 的 append() 串接之後,再以 toString() 轉為 String 型別。

 越強大的程式語言,程式員就越應小心去運用它。而有關 Java/JSP 效能調校的技巧還有很多,本文亦僅能作重點提示。


je edited on 2005-12-16 17:57
reply to postreply to post
臉書「資料庫之道」粉絲團:
http://www.facebook.com/DBtaoist
作者 Re:JSP & Servlets 效能調校提示 [Re:je]
hkdennis2k





發文: 1926
積分: 6
於 2005-12-16 21:49 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
http://www.javaperformancetuning.com/tips/j2ee_srvlt.shtml

先來幾個反証

>提示一 採用正確的 Include 機制

正因為 page Include 和 Include action 在運作上的方式完全不同
所以, 先不要把它放入 performance tuning 的思想中

一般來說, 大文件最不合適放到 page Include 內
但因為它是整個文件 compile 為 class 檔, 重復使用會做成浪費 heap size
Java 基本 performance 理論是減少 class 檔的大小

而且 page Include 也有 另外的問題,

如果有很多頁共用一個 page Include,
一但這一項更新了, 會做出大量文件要求 complie 的情況
(不少 php 寫法的人會用這個來存放 setting / constant....)

如果 server 自動 recompile 生效 (e.g. tomcat, development=true )
會做成每次也要讀取數個不同的檔案有沒有更新而決定會否 re-compile

如果 server 自動 recompile 設為定時再檢查, (e.g. tomcat development=false)
就有可能出現分享了同一 page Include 的不同頁數內容不一樣

只有, 手動事前 compile 和完全不檢查更新 recompile 才安全

而 Include action, 就沒有以上問題
另外, 根據不同 ap server 的實作, 它可能會替你把文件 cache 在 ram 內,
不會做成大量重新讀取

少部份有 ap server 的舊版,
會對多層 page include 的更新改動沒有反應

我個人認為 page Include 是由 cgi(perl)/asp/php 時代留下的錯誤
除非把現有程式轉移至 jsp 上, 否則不要用

>提示二 在 useBean Action 中使用正確的 Scope
比較重要的是
不要把大件的 object 放到 session

以 "由這個 object 開始, hard referenace 而不能被 GC" 來計算

管理放入 session 的 object 的 "質" 比 "量" 更重要

部份 ap server, 會有自動把最近沒有人使用而未過期的 session 存到 harddisk 或其他 media 上的功能
但如果需要在 session 中放入 thread, connection, 和 IO 的, 就要小心了

>提示三 用 HttpServlet 的 init() 方法將資料快取
基本是這樣, 但要留意的是
得到的 Object, 會否出現 timeout / disconnect 或其他失敗
運作時中能否把錯誤重設等等

>提示六 使用 gzip c
這個也是很常見的, 不過用 filter 來做比較好, 能任意掛上/移除

但你要自行試一下, 壓縮後全否更慢

例如在 intranet, bandwidth 沒有有限制的情況
gzip 有否把壓力移到 CPU 上

-------
>>此外,要扔到資料庫中去查詢的 SQL 敘述句........再以 toString() 轉為 String 型別。

不要~!!!!!!!
我們有 sql-injection, XSS, 還有 buffer overflow 等等問題
O/R mapping 為上, PreparedStatement 為中, sql construction 為下下

----------

這篇好像都已經有一段日子
近年的做法是應用 oscache 的 taglib 來做出和 asp.net 一樣簡單的的 cache 和 cache-invaildate 出提昇 jsp 速度

----------

外國人可能不而為然, 但我覺得, 更重要的是 "正確 charset~!"

一般錯誤的 charset 設定, 會比正確的多出 三至五次 來回 decode/encode (byte[] <-> char[])

也做出大量浪費的 byte[], char[] 和 String 要由 GC 清理


reply to postreply to post
作者 Re:JSP & Servlets 效能調校提示 [Re:je]
je





發文: 112
積分: 2
於 2005-12-17 00:07 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
原來真的有人在看,
我還以為只有我這種無業遊民,會在寒流來時在電腦前發呆
一個字一個字慢慢看。

asp.net 從最早的 1.0 版就內建 cache 功能,能容易設定
要快取的內容、控制項或整個頁面…等等,而且功能到 2.0
好像越來越強。
Sun 怎都沒想要內建,只能用 3rd party 提供的?


reply to postreply to post
臉書「資料庫之道」粉絲團:
http://www.facebook.com/DBtaoist
作者 Re:JSP & Servlets 效能調校提示 [Re:je]
hkdennis2k





發文: 1926
積分: 6
於 2005-12-17 00:14 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
je wrote:
Sun 怎都沒想要內建,只能用 3rd party 提供的?


Sun 自行設計/推出的工具, 到目前為止, 那一件是真正好用的.......


reply to postreply to post
作者 Re:JSP & Servlets 效能調校提示 [Re:hkdennis2k]
frex





發文: 16
積分: 0
於 2007-03-13 21:33 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
想請問一下,以下這段話的含義是?
看不太懂,可以說明詳細一點嗎?謝謝你

---
不要~!!!!!!!
我們有 sql-injection, XSS, 還有 buffer overflow 等等問題
O/R mapping 為上, PreparedStatement 為中, sql construction 為下下
---

最近在研究jsp 要如何避免sql-injection, XSS這類的問題
不知道和這篇所提有沒有關,再在苦惱要如何做才能完
全避免這類的問題


reply to postreply to post
作者 Re:JSP & Servlets 效能調校提示 [Re:je]
lijie250





發文: 1
積分: 0
於 2007-03-31 01:42 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
这个比较实用啊~~
对JSP的优化有很大的作用~~


reply to postreply to post
» JWorld@TW »  Servlet/JSP 討論區

reply to topicthreaded modego to previous topicgo to next topic
  已讀文章
  新的文章
  被刪除的文章
Jump to the top of page

JWorld@TW 本站商標資訊

Powered by Powerful JuteForum® Version Jute 1.5.8