IT_Programming/JSP · Servlet

Servlet/JSP performance tuning (Servlet/JSP 성능향상)

JJun ™ 2007. 2. 20. 00:56
 
PTT1: Caching Data를 위하여 HttpServlet 내의 init()를 사용하라.
 
서블릿은 어떤 요청을 처리하기 전에 서블릿 인스턴스를 생성후 서블릿의 init()를 호출하게 된다.
 
이 메소드는 서블릿의 lifetime 내에서 최초 한번 호출되는데, init() 메소드는 static data caching 및 초기에 performance를 많이 소비하는 작업등을 처리하여, performance를 향상 시킬수 있다.
 예를 들어, javax.sql.DataSource interface를 이용하여 JDBC connection pooling를 한다면, 서블릿 init() 에서 DataSource를 취득하여 caching을 한다.
 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;
       }
    ...
    ...
 }

PTT2:
서블릿 및 JSP auto-reloading disable 하여라.
 
PTT3: Control Session
 
많은 애플리케이션은 client request의 연결을 요구한다. 따라서, 하나로 연결지어 생각하여야 하는데, 웹 기반의 애플리케이션 즉, HTTP stateless 이므로 소위 Session이라는 불리우는 각각의 상태를 유지할 책임이 있다. 자바
 
서블릿 기술은 세션을 관리하기 위한 API를 제공하며, 세션을 구현하기위한 여러 메카니즘이 있다.
 Session
HttpSession 객체로 나타내는데, 일단, Session을 사용하는 동안은 많은 cost가 추가된다
.
 HttpSession
은 업데이터될 때 새로이 쓰여지며 사용될때마다 서블릿에 의해 읽혀져야만 한다
.
 
따라서, 우리는 아래와 같은 기술에 의하여 포퍼먼스를 향상시킬 수 있다
.
 -
절대 기본적인 JSP 페이지내에서 HttpSessions를 생성하지 마라
.
 
기본적으로 JSP 페이지내에서 HttpSessions를 생성한다. 만일 우리가 JSP 페이지내에서 HttpSession을 사용하지 않는다면약간의 포퍼먼스 오버헤드를 save 할 수 있다
.
 JSP
페이지내에서 필요하지 않다면, 자동적으로 생성되어지는 HttpSessions를 막기 위하여 아래와 같은 page directive를 사용하라
.
 <%@ page session="false"%>
 - HttpSessions안에 그래프 객체와 같은 너무 큰 객체를 넣지 마라.
 
너가 그래프 객체와 같은 큰 사이즈를 객체를 HttpSession에 넣는다면, 애플리케이션 서버는 매 시간 HttpSession 전체를 처리해야 한다. 이것은 억지로 Java Serialization 과 과도한 연산을 수반하게 된다
.
 HttpSession
증가에 따라 저장되는 객체의 크기로 인하여 throughput은 감소한다. 왜냐하면 Serialization cost 때문이다.
 - session timeout 값을 설정하라.
 
서블릿 엔진은 기본적인 서블릿 timeout을 가지고 있다. 만일 우리가 세션을 제거하지 않거나, timout과 시간이 같아지면서블릿 엔진은 메모리로부터 세션을 제거 할것이다. 따라서, 과도한 크기의 세션 timeout 값이 설정되어 있다면포퍼먼스 및 scalability 에 영향을 미치게 된다. 왜냐하면, 메모리 및 garbage collection 오버헤드 때문이다
.
 
따라서 세션의 timeout값을 가능한 낮은 값으로 유지하라.
 
PTT4: gzip compression을 사용하라.
 
압축이란, 가능한 조그만 공간안에 우리가 원하는 것을 나타내기 위하여 과도한 정보를 제거하는 행위이다.
 
문서를 압축하기 위하여, gzip을 사용하면, HTML 파일에 대하여 다운로드 시간을 dramatical하게 줄일 수 있다
.
 
너의 정보를 더 줄일수 있다. , 더 빠르게 보낼 수 있다. 따라서 우리가 웹 애플리케이션에서 압축하여 콘텐츠를 만든다면, 유저는 더 빠르게 얻을 수 있으며, 더 빠르게 화면에 나타낼수 있다. 단 모든 브라우져가 gzip을 지원하는 것은 아니지만, 우리가 이미 브라우져의 gzip 압축의 제공여부를 체크할 수 있다면 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();
    }
    ...
    ...                       
 } 

PTT5: SingleThreadModel
을 사용하지 마라.
 SingleThreadModel은 한꺼번에 단 하나의 요청을 서블릿이 핸들링하는 것을 보증한다.
 
만일 서블릿이 이 interface를 구현했다면, 서블릿 엔진은 각각 새로운 요청에 대하여 서로 다른 서블릿 인스턴스를 생성하게 된다.이것은 대단히 큰 시스템의 오버헤드를 발생시킨다
.
 
만일 우리가 스레드에 안전한 이슈를 해결해야 한다면, interface를 구현하는 대신 다른 방법을 사용해라
.
 SingleThreadModel interface
는 서블릿 2.4 스펙안에서 deprecated 되었다.
 
PTT 6: thread pool을 사용하라.
 이 부분은 건너가겠음.. 이미 많은 WAS내에서 request에 대하여 처리를 위한 스레드 풀을 사용하고 있음.
 
PTT 7: 옳은 include mechanism을 선택하라.
 JSP 페이지내에 파일을 include하기 위해선 두가지 방법이 있다.
 include directive (<%@ include file="test.jsp" %>)
include action (<jsp:include page="test.jsp" flush="true" />)이다
.
 include directive
는 서블릿으로 변환시 파일이 포함되며, include action 각각의 서블릿으로 변환되어요청을 처리시에 매번 컨텐츠를 만들게 된다. 따라서 유저가 페이지를 요청할때, Include directive include action보다는 더 빠르다. 따라서, 종종 포함한 파일이 바꿔지 않는다면, include directive를 사용하는 것이 포퍼먼스에 더 좋다.
 
PTT 8: useBean action 안에서 옳은 scope를 선택하라.
 대부분 JSP를 사용하는 파워풀한 방법중에 하나가 JavaBean 콤퍼넌트들과 협력하는 것이다.
 JavaBeans
<jsp:useBean> action tag를 사용하여 JSP 페이지내에 직접 embedded될 수 있다
.
 syntax
는 아래와 같다.
 <jsp:useBean id="name" scope="page|request|session|application" class=
   "package.className" type="typeName">
 </jsp:useBean>
  scope 속성은 bean visibility scope를 정의한다. 기본적은 값으로 scope 속성은 page 이다.
 
우리가 우리의 애플리케이션 요구에 맞추어 정확한 scope를 선택해야 한다. 그렇지 안다면, 애플리케이션의 포퍼먼스에 영향을 미치게 된다.
 예를 들어, 만일 우리가 단지 특정 요청에 대해서만 객체가 필요한데, 우리가 scope session으로 한다면, 객체는 우리의 요청이 수행된 이후에서 메모리로부터 그 객체를 명시적으로 지우기 전까지 또는 서불릿 엔진에 설정한 세션의 timeout 때까지 메모리에 상주하게 된다.
 
우리가 옳지않은 scope 속성 값을 선택한다면, 메모리 및 garbage collection로 인하여 포퍼먼스에 영향을 미치게 된다
.
 
따라서, 정확한 scope를 객체에 대하여 설정하며, 그 객체의 사용이 끝났다면 즉시 지워야 한다.

[ 기타 기술들... ]
 - string concatenation을 피하라.
 '+' operation
을 이용하여 문자열을 붙힌다면, 많은 temporary objects의 생성을 야기시킨다.
 
왜냐하면 string immutable objects(불변 객체)이기 때문이다
.
 '+'
를 대신하여 StringBuffer를 사용하라.
 
 - System.out.println()의 사용을 피하라.
 System.out.println() disk I/O
의 지속에 대하여 동기적으로 동작한다. 그리고, 중대한 throughput을 느리게 할 수 있다.
 
가능한 많이 System.out.println의 사용을 피해야 한다.
 
 - ServletOutputStream PrintWriter
 PrintWriter는 약간의 오버헤드를 발생한다. 왜냐하면 character-set conversions를 처리하여 바이너리 형태로 반환한다.
 
반면에, ServletOutputStream은 바로 바이너리 형태로 반환한다.