글쓴이: 이원영(javaservice) 2001/02/14 15:16:10 조회수:10302 줄수:298
최근수정일자 : 2001.02.17
최근수정일자 : 2001.02.21(requestmon.jsp elapsed time 추가)
최근수정일자 : 2001.03.11(WebSphere 3.5.3 용 추가)
최근수정일자 : 2001.03.26(WebSphere 3.0.2.4 용 추가)
최근수정일자 : 2001.05.24(WebSphere 3.5.4 용추가 및 trace.dumptrigger 추가)
최근수정일자 : 2001.07.09(JSP 0.91/1.0/1.1, service 메소드두번호출해결)
최근수정일자 : 2001.10.30(일부 문맥 수정)
NOTE: 최근 버전(2001.07.09일자)의 기능 추가 사항
- 개발자가 서블렛기반의 service() 를 override 하여 개발할 경우
requestmon 에서 동일한 호출이 두번씩 나타나던 문제를 해결.
- JSP 1.0 모드에서만 되고, JSP 0.91 이나 JSP 1.1 모드에서는 동작하지 않던 문제를
해결.
어플리케이션서버 혹은 서블렛엔진를 사용하는 각 사이트에서 성능 진단 및 튜닝을
하다보면, 가장 답답한 것 중의 하나는 다음과 같은 것입니다.
"서블렛엔진이 죽어요... 서비스가 응답이 없어요. hang이 걸렸어요, 고쳐주세요."
그러나, 짧게는 2-3일, 길게는 일주일정도 전체 소스에 대한 Review 와 S/W 디자인
을 확인하고, 응답이 느린 서비스를 찾아내고, 해당 시스템에 들어오는 요청량을
분석하고.... 그러다 보면 10중 8-9는 어플리케이션 소스에 다소 문제가 있는 것으로
결론이 납니다. 잘 될때는 항상 잘 되죠. 문제는 request 가 폭주할 시에는 어떻게
동작하도록 해야 하는가 라는 깊이 있는 고민이 없이 작성된 어플리케이션 소스와
각종 파라메터는 서비스 폭주시에 여지없이 본색(?)을 드러냅니다.
여기서 우리의 절대절명의 과제는 이러한 문제를 야기하는 어플리케이션이 어떤
어플리케이션이었느냐를 잡아내는 것입니다. 특히 요청이 들어와서 오랫동안 끝나지
않는 서비스가 무엇인가를 찾는 일입니다.
첫번째 간단한 방법은 웹서버(IBM HTTP Server)의 httpd.conf 파일에서 Elapsed Time 을
측정할 수 있도록 %T 옵션을 common 로그형태에 추가하여 1초단위로 나타나는 응답시간을
모니터링 하는 것입니다.
[httpd.conf]
.........................
LogFormat "%h %l %u %t \"%r\" %>s %b" common
===>
LogFormat "%h %l %u %t \"%r\" %>s %b %T" common
이렇게 함으로써, 해당 URL에 따른 응답시간이 초 단위로 access_log 파일에 추가로
기록되므로, 응답이 느린 서비스를 확인하는데 도움이 됩니다.
그러나, 막상 문제가 발생하는 당시에는 현재 동작중인 서비스에 대해서는 아무런
로그도 남지 않는다는 것입니다. 웹서버의 access_log는 처리가 끝이나야 그제서야
로그를 남기므로, 현재 동작하고 있는 서비스가 무엇인지 실시간으로 볼 방법이 없다는
것이지요. 예를들어 뭔가 현재 서비스하고 있는 갯수, 즉, 웹서버와 어플리케이션서버
사이의 연결 socket 갯수는 자꾸 증가하는데, 어떤 서비스가 수행 중이기 때문에
증가했는지를 확인할 방법이 없다는 것입니다.
(NOTE: 대부분의 서블렛엔진은 웹서버와 서블렛엔진 사이의 통신을 TCP/IP Socket으로
하고 있습니다. 그 port 는 설정하기 나름이지만, 8080, 8090 등입니다.
따라서, "netstat -n | grep .8080" 혹은 "netstat -n | grep .8080 |wc -l"등의
명령어로, 현재 몇개가 열려있는지를 확인하실 수 있습니다. 서블렛엔진에
따라서는 KeepAlive Connection 을 사용하기도 하기 때문에, 항상 일정수치가
유지될 수도 있습니다.
반면, IBM WebSphere 의 경우는 OSE 라는 방식으로 통신하는데, 이는
"netstat -n | grep asibmoselink" 를 통해 그 갯수를 모니터링 할 수 있습니다.
)
아래의 방법은 서블렛엔진 혹은 어플리케이션서버에서 현재 서비스하고 있는
Servlet 이나 JSP의 리스트를 다음과 같은 형태로 실시간으로 보여주고, 필요한 경우,
응답이 느린 서비스들만 대상으로 하여 특별한 로그파일에 기록해 주는 기능을 추가하는
방법입니다.
[http://..../requestmon.jsp ]
===============================================================================
IBM WebSphere V3 Request Monitor version 1.1
CurrentTime: 20010709/02:04:54
CALL TIME ELASPED IP ADDRESS URI
-------------------------------------------------------------------------------
20010709/02:04:52 2033 127.0.0.1 /requestmon.jsp
20010709/02:04:31 23035 203.247.159.11 /servlet/MyServlet?name=lwy
20010709/02:04:31 23035 203.247.159.11 /servlet/MyServlet?name=lwy
20010709/02:04:31 23035 203.247.159.11 /servlet/MyServlet?name=lwy
20010709/02:04:31 23035 203.247.159.11 /servlet/MyServlet?name=lwy
20010709/02:04:31 23035 203.247.159.11 /servlet/MyServlet?name=lwy
-------------------------------------------------------------------------------
NOTE: This is only for debugging so we do NOT support this feature officially.
WonYoung Lee. lwy@kr.ibm.com, javaservice@hanmail.net IBM Korea.
===============================================================================
비단 IBM WebSphere Application Server Version 3 이 외의 다른 어플리케이션 서버
제품에서도 동일하게 적용할 수 있도록 일반적인 방법을 구상해 보았습니다.
엔진 소스를 decompile 하여 적용하는 방법을 기술하면 다음과 같습니다.
(1) 해당 어플리케이션서버에서 제공하는 jar 파일 속에 javax.servlet.http.HttpServlet
클래스를 찾으십시요. 통상 servlet.jar 라는 이름으로 존재할 가능성이 있으나,
어디까지나 해당 어플리케이션서버 혹은 서블렛엔진 제품에 따라 다르겠지요.
WebSphere 의 경우, servlet.jar 파일이며, BEA WebLogic 의 경우, weblogicaux.jar
파일에 들어 있습니다.
# cp servlet.jar /tmp/src/
# cd /tmp/src/
# jar -xvf servlet.jar
(2) 재주껏 decompile 하여 HttpServlet 클래스의 source 를 확보하시고, 다시 컴파일
할 수 있는 환경을 마추십시요...
추천하는 decompiler 는 jad 입니다.
http://www.geocities.com/SiliconValley/Bridge/8617/jad.html
# cd /tmp/src/javax/servlet/http/
# jad -sjava *.class
(3) HttpServlet 클래스의 public void service(..) 부분에 다음과 같은 로직을
삽입합니다.
# cd /tmp/src/javax/servlet/http/
# vi HttpServlet.java
....
public void service(ServletRequest servletrequest,
ServletResponse servletresponse) throws ServletException, IOException
{
HttpServletRequest httpservletrequest;
HttpServletResponse httpservletresponse;
try
{
httpservletrequest = (HttpServletRequest)servletrequest;
httpservletresponse = (HttpServletResponse)servletresponse;
}
catch(ClassCastException _ex)
{
throw new ServletException("non-HTTP request or response");
}
service(httpservletrequest, httpservletresponse);
}
====>
public void service(ServletRequest servletrequest,
ServletResponse servletresponse) throws ServletException, IOException
{
HttpServletRequest httpservletrequest;
HttpServletResponse httpservletresponse;
try
{
httpservletrequest = (HttpServletRequest)servletrequest;
httpservletresponse = (HttpServletResponse)servletresponse;
}
catch(ClassCastException _ex)
{
throw new ServletException("non-HTTP request or response");
}
//-----------------------------------------------------------
org.jdf.requestmon.ServiceTrace trace =
org.jdf.requestmon.ServiceTrace.getInstance();
trace.startTrace(httpservletrequest);
try {
//-----------------------------------------------------------
service(httpservletrequest, httpservletresponse);
//-----------------------------------------------------------
}
finally {
trace.endTrace(httpservletrequest);
}
//-----------------------------------------------------------
}
....
NOTE: "public void service(...)" 입니다. "protected..."로 시작하는 메소드에
하시면 안됩니다.
(4) 이렇게 변경된 소스를 다시 컴파일 합니다. org.jdf.requestmon.* 패키지는 아래
첨부파일에서 다운 받을 수 있습니다.
# cd /tmp/src/
# javac javax/servlet/http/HttpServlet.java
(5) 새로 컴파일 된 javax.servlet.http.HttpServlet 클래스와 org.jdf.requestmon.*
패키지를 적당한 jar 파일로 묶습니다.
# cd /tmp
# mkdir /tmp/requestmon/
# cp /tmp/requestmon3.5.2-4.jar /tmp/requestmon/
# cd /tmp/requestmon/
# jar -xvf requestmon3.5.2-4.jar
# mkdir /tmp/module
# cp /tmp/src/javax/servlet/http/HttpServlet.class /tmp/module/javax/servlet/http/
# cd /tmp/requestmon/
# cp -R /tmp/requestmon/org /tmp/module/
# jar -cvf0 requestmon.jar *
이제 requestmon.jar 에는 HttpServlet.class 와 org.jdf.requestmon.* 패키지가
들어 있게 됩니다.
이 jar 파일을 해당 서블렛엔진에 영향을 미칠 수 있도록 해당 엔진에 맞게 적용
하십시요. 대부분의 경우, 해당 엔진의 CLASSPATH servlet.jar 보다 앞쪽에 위치토록
하면 족할 것입니다.
(6) 아래의 글을 통해 필요한 옵션을 엔진에 맞게 지정하십시요.
===============================================================================
IBM WebSphere Application Server Verion 3.0.2.x, 3.5.x 의 경우는 미리 컴파일 해
두었습니다. 적용방법은 다음과 같습니다.
적용방법:
(1) 첨부한 requestmon???.jar 를
적용하듯 가장 앞쪽에 설정합니다.(servlet.jar 와 ibmwebas.jar 보다 먼저...)
requestmon3.0.2.2-4.jar : 3.0.2.2, 3.0.2.3, 3.0.2.4 용
requestmon3.5.0.jar : 3.5.0 용
requestmon3.5.2-4.jar : 3.5.2, 3.5.3, 3.5.4 용
예:) $WAS_HOME/bin/admin.config
.........
com.ibm.ejs.sm.adminserver.classpath=D\:/WebSphere/AppServer/efix/requestmo
n3.5.2-4.jar;D\:/WebSphere/AppServer/lib/ibmwebas.jar;.......
......
NOTE: WebSphere 3.0.2.0, 3.0.2.1 및 3.5.1 용은 해당 fixpack 을 (현재) 갖고 있지
않은 관계로 미리 만들지 못했습니다. 필요하시면 직접 하시고, 이곳에 다시 올려
주세요.
NOTE: javax.servlet.http.HttpServlet 클래스는 대부분 잘 바뀌지 않으나, 그래도
fixpack 이 올라갈 때 약간씩 바뀔 수 있으므로 반드시 버전을 마추어 주어야
합니다.
(2) requestmon.jsp 는 적당한 웹 경로의 JSP 디렉토리에 두시고 호출하시면 됩니다.
requestmon.jsp는 JSP 1.0 기반의 태그를 포함하고 있으므로 JSP 0.91 에서
운영하시려면
<@ session="false" content_Type="text/html;charset=euc-kr" %>
<% ... SimpleDateFormat df = ... %> <-- "!" 삭제
위와 같이 첫 두 라인을 수정하셔야 할 겁니다.
NOTE: 과거 버전의 requestmon.jsp를 갖고 있다면 2001.07.09일자로 다시 받으셔야
합니다. org.jdf.trace.* 패키지가 org.jdf.requestmon.* 패키지로 이름이 바뀌었습니다.
(3) requestmon 모듈은 몇가지 옵션을 제공합니다. WebSphere 의 관리콘솔에서 매개변수
부분(JVM의 실행옵션)에 다음과 같은 System Parameter 지정으로 그 기능을 조절할
수 있습니다.
-Dtrace.log=/tmp/trace.log \
-Dtrace.delaytime=5000 \
-Dtrace.dumptrigger=90
1) 로그 파일 위치 지정하기
-Dtrace.log=/tmp/trace.log
만약, 위 옵션을 지정하지 않으면, "현재디렉토리"에 "trace.log"라는 파일이
지정됩니다.
NT : C:\winnt\system32\trace.log
UNIX: WAS를 기동한 디렉토리(통상 /usr/WebSphere/AppServer/bin/trace.log )
2) -Dtrace.delaytime=5000 (micro-second 단위)
Elapsed Time 이 위에서 지정된 시간을 넘어가는 요청만 로그에 남깁니다. 만약,
지정치 않으면, default 는 3000(3초) 입니다.
3) -Dtrace.dumptrigger=90
기존 requestmon 버전의 문제는 정작 hang 이 발생하면 requestmon.jsp조차 실행이
되지 않기 때문에, 현재 무엇이 돌고 있는지 볼 방법이 없었습니다.
위 옵션에서 지정한 갯수 이상의 요청이 동시에 들어왔을 때, 현재 수행중인 모든
서비스 내용을 trace.log 파일에 dump 를 해 줍니다.
지정치 않을 경우, default 는 90 입니다. 해당 서블렛엔진에서 최대로 들어 올 수
있도록 설정된 수치보다는 위 수치가 낮게 잡혀 있어야 실질적으로 dump 가 남을
것입니다.
일단, dump 가 일어나면, 3분이내에 추가적인 dump 는 하지 않습니다.
NOTE: 모든 매 요청시마다 필요한 정보를 메모리에 저장한 후 서비스가 끝난 시점에
다시 필요한 정보를 뽑아 내는 것과 같은 체크를 하므로, 약간의 성능저하는
있습니다. 따라서, Benchmark Test 와 같은 상황에서는 사용치 않으시는 것이
바람직할 겁니다.
NOTE: 본 requestmon 모듈은 엔진 내부의 클래스를 변경하여 기능을 첨가한 것이므로
이 모듈을 사용함으로 인해 발생하는 여하한의 문제에 대하여 IBM 혹은 필자는
책임지지 않습니다. 오직 debugging 의 용도로만 사용하세요....
-------------------
2001.10.30
JDK 1.3 의 경우는 j2ee.jar 파일 내에 javax.servlet.http.HttpServlet 이 들어 있습니다.
결국 j2ee.jar 파일을 풀어서("jar -xvf j2ee.jar") HttpServlet 을 변경한 후, 이를
org.jdf.requestmon.* 패키지와 함께 j2ee.jar 파일로 다시 묶으시면 됩니다.
("jar -cvf0 j2ee.jar *")
from:
http://www.javaservice.net/~java/bbs/read.cgi?m=appserver&b=was&c=r_p&n=982131370
프로그램 소스는 주소로 가서 받으세요.
'StoreHouse > Server' 카테고리의 다른 글
Windows 2000 과 IIS 관리자들을 위한 점검사항 리스트 (0) | 2006.04.11 |
---|---|
서버관리 유틸리티 SSU(Superuser Server Utility)설치 및 운영 (0) | 2005.03.22 |
모모웹시스템 2차 장애진단 보고서 (0) | 2005.03.08 |
proftp 명령어 (0) | 2005.02.21 |
Apache-2.0.49 + MySQL-4.0.18 + PHP-4.3.6 (0) | 2005.02.17 |