首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 程式設計入門

JSP/Servlet 效能調優七大實戰技巧

     編輯:Java 程式設計入門

前言

面對客戶抱怨「頁面太慢」、流量暴增時系統崩潰,本文提供七個立竿見影的調優方向,涵蓋程式碼層面與容器配置層面。

技巧一:init() 方法快取靜態資源

Servlet 生命週期中 init() 僅執行一次,適合初始化昂貴資源:

public class ControllerServlet extends HttpServlet {
    private DataSource dataSource;

    @Override
    public void init(ServletConfig config) throws ServletException {
        super.init(config);
        try {
            Context ctx = new InitialContext();
            dataSource = (DataSource) ctx.lookup("jdbc/testDS"); // JNDI 查詢只做一次
        } catch (NamingException e) {
            throw new ServletException("DataSource lookup failed", e);
        }
    }

    public DataSource getDataSource() { return dataSource; }
}

避免每請求重複 JNDI lookup、建立連線池。

技巧二:生產環境關閉自動重載

  • 開發時:reloadable="true" 方便熱部署。
  • 生產時:必須設為 false。類載入器持續掃描檔案變更會消耗大量 CPU/記憶體,且可能導致 PermGen/Metaspace 洩漏。

技巧三:審慎使用 HttpSession

誤用後果修正
預設每頁建立 Session大量無用 Session 物件、序列化開銷JSP 頁面指令 <%@ page session="false" %>
Session 存放大物件 (查詢結果集、集合)序列化/反序列化慢、記憶體暴增只存 ID/Token,資料放快取 (Redis/Ehcache)
用完不釋放Session 逾時前長期佔用記憶體明確呼叫 session.invalidate()
逾時設定過長 (預設 30 分鐘)併發用戶多時記憶體壓力大依業務縮短 (如 10-15 分鐘)

技巧四:啟用 GZIP 壓縮回應

public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
    String encoding = req.getHeader("Accept-Encoding");
    OutputStream out;

    if (encoding != null && encoding.contains("gzip")) {
        resp.setHeader("Content-Encoding", "gzip");
        out = new GZIPOutputStream(resp.getOutputStream());
    } else if (encoding != null && encoding.contains("deflate")) {
        resp.setHeader("Content-Encoding", "deflate");
        out = new DeflaterOutputStream(resp.getOutputStream());
    } else {
        out = resp.getOutputStream();
    }
    // 後續寫入 out...
}

HTML/JSON/CSS/JS 通常壓縮率 70-90%,大幅降低傳輸時間。現代容器 (Tomcat 9+, Jetty, Undertow) 可直接在 server.xml 設定 Compression="on" 免寫代碼。

技巧五:使用執行緒池

  • 預設模式:每請求一執行緒,建立/銷毀開銷大,高併發下系統負載尖峰劇烈。
  • 執行緒池:啟動時建立核心數 (minThreads),忙碌時擴充至上限 (maxThreads),閒置回收。負載曲線平滑,吞吐量穩定。
  • Tomcat 配置:<Executor name="tomcatThreadPool" namePrefix="catalina-exec-" maxThreads="200" minSpareThreads="25" /> 並讓 Connector 參考 executor="tomcatThreadPool"。

技巧六:選擇正確的頁面包含機制

  • 靜態包含:<%@ include file="header.jsp" %> → 編譯期合併為單一 Servlet,效能最佳,適合不變片段 (頁首/頁尾/選單)。
  • 動態包含:<jsp:include page="dynamic.jsp" flush="true" /> → 執行期獨立編譯/執行,支援參數傳遞、條件包含,但有額外請求轉發開銷。

原則:能用靜態包含就不用動態包含。

技巧七:正確設定 JavaBean 生命週期

<jsp:useBean id="user" scope="request" class="com.example.User" />
scope生命週期適用場景
page單頁請求處理期間 (預設)頁面專用暫存物件
request單次 HTTP 請求 (含 forward)Controller 產生、View 消費的資料
session用戶會話期間登入用戶、購物車 — 慎用
applicationWeb 應用存活期間共享快取、配置 — 需同步

錯誤範例:請求級資料設為 session,導致請求結束後物件殘留,增加 GC 壓力與記憶體佔用。

其他微優化

  • 字串串接:迴圈/大量串接用 StringBuilder (非同步) 而非 +。
  • 避免 System.out.println:同步 I/O 阻塞,改用 log4j2/slf4j 非同步 Appender。
  • 輸出流選擇:二進制輸出用 ServletOutputStream,文字輸出用 PrintWriter (內建編碼轉換),依內容類型決定。

總結

效能調優無銀彈,但上述七大方向覆蓋 80% 以上常見瓶頸。原則:減少物件建立、縮短生命週期、降低 I/O、平滑併發。調優前必測量 (JMeter/LoadRunner + APM),調優後必驗證。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved