서비스 및 사용자 모니터링

자바 애플리케이션 서비스와 트랜잭션

자바 애플리케이션은 여러 개의 애플리케이션 서비스로 구성되어 있다. 애플리케이션 서비스는 고정된 개념이 아니고, 호출 건수와 응답 시간 등의 성능 데이터를 수집하는데 기준이되는 통계 단위이다.

애플리케이션 서비스를 애플리케이션이라고도 한다. 그러나 이는 전체 프로그램을 의미하는 애플리케이션과는 다른 의미에서 사용된다. 그 차이는 전체 맥락 속에서 파악해야 한다.

일반적으로 애플리케이션 서비스는 업무를 기준으로 한다. 예를 들어, 쇼핑몰 애플리케이션에서는 제품 목록 보기, 제품 상세 내역 보기, 장바구니에 담기, 주문, 결제 등이 애플리케이션 서비스가 될 수 있다. 그런데 하나의 업무가 세분화될 수 있고, 성능 관리 측면에서는 세부 단계 별로 성능 데이터를 수집하는 것이 바람직하기 때문에 애플리케이션 서비스가 업무 구분보다 더 세분화되는 경향이 있다.

일차적으로 웹 애플리케이션에서는 URI가 애플리케이션 서비스를 지칭하는 대표적인 방법이다.

/view.jsp
/order.jsp
/pay.jsp

그러나 모든 요청의 URI가 동일해서 요청 파라미터로 애플리케이션 서비스를 구분해야하는 경우도 있을 수 있다.

/service.do?action=view
/service.do?action=order
/service.do?action=pay

이 경우에 HTTP GET 방식이 아닌 HTTP POST 방식으로 파라미터가 전달될 수 있기 때문에 URI가 아닌 다른 방법으로 애플리케이션 서비스를 구분해야 한다.

또한 웹 애플리케이션이 아닌 경우에는 특정 클래스의 특정 메소드로 애플리케이션 서비스를 구분해야 한다.

example.ViewManager 클래스의 view 메소드
example.OrderManager 클래스의 order 메소드
example.PayManager 클래스의 pay 메소드

트랜잭션은 사용자가 애플리케이션 서비스를 요청하여 해당 애플리케이션 서비스가 자바 애플리케이션에서 수행된 것을 의미한다. 호출 건수, 평균 응답 시간 등은 트랜잭션 처리 결과를 바탕으로 수집하는 성능 데이터이고, 애플리케이션 서비스는 메타 데이터의 역할을 한다.

애플리케이션 서비스 시작점

애플리케이션 서비스 시작점은 트랜잭션이 시작하는 위치이다. 엄밀하게 트랜잭션 시작점은 클라이언트 요청을 받아들이는 맨 앞단의 네트워크 모듈이 된다. 하지만 대부분의 요청을 동일한 포트 번호로 받아들이기 때문에, 이 지점에서는 애플리케이션 서비스를 구분할 수 없다. 트랜잭션과 관련한 성능 데이터는 애플리케이션 서비스를 기준으로 수집되기 때문에 애플리케이션 서비스 시작점은 애플리케이션 서비스를 구분할 수 있는 최초의 위치가 되어야 한다.

모니터링하는 자바 애플리케이션이 WAS이냐 아니냐에 따라서 애플리케이션 서비스 시작점을 설정하는 방법이 달라진다.

웹 애플리케이션

WAS에 기반한 웹 애플리케이션의 애플리케이션 서비스 시작점은 javax.servlet.http.HttpServlet 클래스의 service(ServletRequest, ServletResponse) 메소드가 된다. 이 경우에는 별도의 설정이 필요없다.

그런데 이 메소드를 재정의한(override) 서블릿을 모니터링하려면 제니퍼 에이전트의 http_service_class 옵션으로 해당 서블릿을 설정해야 한다. 여러 개는 [;]을 구분자로 구분해서 설정한다. 예를 들어, example.AServlet과 example.BServlet 클래스가 javax.servlet.http.HttpServlet 클래스를 상속하고 service 메소드를 재정의했다면 다음과 같이 설정한다.

http_service_class = example.AServlet;example.BServlet

수정한 http_service_class 옵션을 반영하려면 제니퍼 에이전트를 설치한 자바 애플리케이션을 재시작해야 한다. http_service_class 옵션에 등록하지 않아도 WAS들이 제공하는 다음 서블릿은 자동으로 애플리케이션 서비스 시작점이 된다. 이 클래스들은 대부분 WAS 별 JSP의 상위 서블릿 클래스이다. 따라서 대부분의 WAS에서 JSP에 대한 별도의 설정을 할 필요가 없다.

javax.servlet.http.HttpServlet
com.evermind.server.http.JSPServlet
com.caucho.jsp.JavaPage
jrun.jsp.runtime.HttpJSPServlet
allaire.jrun.jsp.HttpJSPServlet
weblogic.servlet.jsp.JspBase

service가 아닌 ServletRequest과 ServletResponse 클래스를 파라미터로 하는 메소드를 애플리케이션 서비스 시작점으로 설정하려면 제니퍼 에이전트의 http_service_method 옵션을 사용한다. 수정한 http_service_method 옵션을 반영하려면 제니퍼 에이전트를 설치한 자바 애플리케이션을 재시작해야 한다.

http_service_method = doFilter

http_service_method 옵션에는 파라미터 개수와 상관없이 처음 2개의 파라미터가 ServletRequest와 ServletResponse인 메소드를 지정할 수 있다. 그러나 2개 이상의 메소드를 지정할 수는 없다. 그렇지만 service 메소드는 자동으로 등록되기 때문에 서블릿을 모니터링하는데는 문제가 없다.

javax.servlet.Filter 인터페이스를 구현한 필터 클래스를 애플리케이션 서비스 시작점으로 설정하려면 다음과 같이 한다. 다음의 예는 javax.servlet.Filter 인터페이스를 구현한 example.FrontFilter 클래스를 애플리케이션 서비스의 시작점이라고 가정한다.

http_service_class = example.FrontFilter
http_service_method = doFilter

그리고 성능 데이터를 수집할 필요가 없는 URI는 모니터링하지 않을 수 있다.

우선 제니퍼 에이전트의 ignore_url 옵션을 통해서 모니터링하지 않을 URI를 설정한다.

ignore_url = /check.jsp,/test.jsp

그리고 제니퍼 에이전트의 ignore_url_postfix 옵션을 통해서 특정 형태로 끝나는 URI를 모니터링하지 않을 수 있다.

ignore_url_postfix = .gif .GIF .jpg .JPG .zip .html .HTML .txt .css .js
.swf .htc .HTC .png .PNG

또한 제니퍼 에이전트의 ignore_url_prefix 옵션을 통해서 특정 형태로 시작하는 URI를 모니터링하지 않을 수 있다.

ignore_url_prefix = /admin,/console

일반 자바 애플리케이션

WAS를 사용하지 않는 일반 자바 애플리케이션의 경우에는 제니퍼 에이전트의 tx_server로 시작하는 옵션을 통해서 애플리케이션 서비스 시작점을 설정한다. 수정한 tx_server로 시작하는 옵션을 반영하려면 제니퍼 에이전트를 설치한 자바 애플리케이션을 재시작해야 한다.

예를 들어, 주문을 처리하는 클래스가 example.OrderManager라고 가정하자. 이를 애플리케이션 서비스의 시작점으로 설정하려면 제니퍼 에이전트의 tx_server_class 옵션으로 다음과 같이 설정한다.

tx_server_class = example.OrderManager

그리고 결제를 처리하는 클래스가 example.PayManager라고 가정하자. 이 클래스도 애플리케이션 서비스 시작점으로 설정하려면 [;]을 구분자로 tx_server_class 옵션에 설정한다. tx_server_class 옵션뿐만 아니라 애플리케이션 서비스 시작점과 관련한 모든 옵션에 2개 이상을 설정하려면 [;]을 구분자로 사용한다.

tx_server_class = example.OrderManager;example.PayManager

그런데 애플리케이션 서비스 시작점은 특정 클래스의 특정 메소드를 의미한다. 따라서 앞에서와 같이 설정하면 example.OrderManager 클래스의 모든 메소드가 애플리케이션 서비스 시작점으로 인식된다.

따라서 특정 메소드만을 애플리케이션 서비스 시작점으로 설정하려면 제니퍼 에이전트의 tx_server_target_method 옵션으로 설정한다.

tx_server_target_method = order

그런데 애플리케이션 서비스 시작점으로 설정한 클래스들 중에서 이름이 동일한 메소드가 있고, 이 중 특정 클래스의 특정 메소드만을 애플리케이션 서비스 시작점으로 설정하려면 다음과 같이 구체적으로 설정한다.

tx_server_target_method = example.OrderManager.order

반대로 특정 메소드만을 애플리케이션 서비스 시작점에서 제외하려면 제니퍼 에이전트의 tx_server_ignore_method 옵션으로 설정한다.

tx_server_ignore_method = example.OrderManager.someMethod

메소드의 접근자를 통해서도 애플리케이션 서비스 시작점을 설정할 수 있다. 예를 들어 public 접근자와 접근자가 없는 메소드를 애플리케이션 서비스 시작점으로 등록하려면 다음과 같이 설정한다.

tx_server_access_method = public;none

tx_server_access_method 옵션에 설정이 가능한 값은 다음과 같다.

그리고 특정 클래스를 상속한 모든 클래스가 애플리케이션 서비스 시작점인 경우에는 제니퍼 에이전트의 tx_server_super 옵션을 사용한다. 예를 들어, example.BaseAction을 상속한 모든 클래스를 애플리케이션 서비스 시작점으로 설정하려면 다음과 같이 설정한다.

tx_server_super = example.BaseAction

그러나 이 경우에 직접적으로 상속받은 클래스만이 애플리케이션 서비스 시작점이 된다. 예를 들어, A 클래스가 example.BaseAction 클래스를 상속하고 B 클래스가 A 클래스를 상속했다면, A 클래스는 애플리케이션 서비스 시작점으로 인식하지만 B 클래스는 애플리케이션 서비스 시작점으로 인식하지 않는다.

그리고 특정 인터페이스를 구현한 모든 클래스가 애플리케이션 서비스 시적점인 경우에는 제니퍼 에이전트의 tx_server_interface 옵션을 사용한다. 예를 들어, example.IAction 인터페이스를 구현한 모든 클래스를 애플리케이션 서비스 시작점으로 설정하려면 다음과 같이 설정한다.

tx_server_interface = example.IAction

그러나 이 경우에 직접적으로 구현한 클래스만이 애플리케이션 서비스 시작점이 된다. 예를 들어, A 클래스가 example.IAction 인터페이스를 구현하고 B 클래스가 A 클래스를 상속했다면, A 클래스는 애플리케이션 서비스 시작점으로 인식하지만 B 클래스는 애플리케이션 서비스 시작점으로 인식하지 않는다.

그리고 클래스의 이름을 이용해서도 애플리케이션 서비스 시작점을 설정할 수 있다. 이 경우에는 제니퍼 에이전트의 tx_server_prefix, tx_server_postfix, tx_server_ignore_prefix 옵션을 사용한다. 예를 들어, 이름이 example.action으로 시작하는 모든 클래스를 애플리케이션 서비스 시작점으로 설정하려면 다음과 같이 한다.

tx_server_prefix = example.action

또한 이름이 Action으로 끝나는 모든 클래스를 애플리케이션 서비스 시작점으로 설정하려면 다음과 같이 한다.

tx_server_postfix = Action

그리고 특정 이름으로 시작하는 클래스를 애플리케이션 서비스 시작점에서 제외하려면 제니퍼 에이전트의 tx_server_ignore_prefix 옵션을 사용한다. 이 옵션은 다른 모든 옵션에 우선한다.

tx_server_ignore_prefix =

제니퍼 에이전트의 tx_server로 시작하는 옵션을 통해서 동일한 내용을 다양한 방법으로 설정할 수 있다. 애플리케이션 서비스 시작점을 설정하는데 있어서 tx_server_target_method 옵션을 통해서 실제로 애플리케이션 서비스 시작점인 메소드만을 설정하도록 한다.

예를 들어, pkg.ClassA와 pkg.ClassB 클래스가 있다. 여기서 ClassA 클래스의 run 메소드와 ClassB 클래스의 process 메소드가 애플리케이션 서비스 시작점이라고 가정한다. 그런데 ClassB 클래스에 run 메소드가 존재하고 이 메소드는 애플리케이션 서비스 시작점과는 상관이 없다면 다음과 같이 설정한다.

tx_server_class = pkg.ClassA;pkg.ClassB
tx_server_target_method = run;process
tx_server_ignore_method = pkg.ClassB.run

또는 다음과 같이 설정할 수도 있다.

tx_server_class = pkg.ClassA;pkg.ClassB
tx_server_target_method = pkg.ClassA.run;pkg.ClassB.process

애플리케이션 서비스 네이밍

애플리케이션 서비스 이름은 APPLS 테이블에 저장된다. 기본적으로 웹 애플리케이션은 URI가 애플리케이션 서비스 이름이 되고, tx_server 옵션으로 설정한 경우에는 클래스 이름과 메소드 이름이 애플리케이션 서비스 이름이 된다. 그런데 요청 파라미터 값이나 특정 메소드의 파라미터 혹은 반환 값 등을 이용해서 애플리케이션 서비스 이름을 설정할수도 있다.

이렇게 애플리케이션 서비스 이름을 다양한 방식으로 설정하는 것을 애플리케이션 서비스 네이밍이라고 한다.

웹 애플리케이션

웹 애플리케이션은 요청 URI가 애플리케이션 서비스 이름이 된다. 그런데 웹 애플리케이션 프레임워크의 발전으로 애플리케이션 서비스가 URI만으로는 구분되지 않는 경우가 많아지고 있다. 이런 경우에는 요청 파라미터를 이용해서 애플리케이션 서비스 이름을 구체적으로 설정할 수 있다. 이를 위해서 제니퍼 에이전트의 url_additional_request_keys 옵션에 요청 파라미터 이름을 설정한다.

url_additional_request_keys = key1,key2

앞의 경우에는 다음 코드가 반환하는 파라미터 값을 사용해서 애플리케이션 서비스 이름을 결정한다.

request.getParameter(” key1” );
request.getParameter(” key2” );

예를 들어, 특정 요청에 대한 애플리케이션 서비스 이름은 다음과 같이 결정된다.

http://127.0.0.1:8080/app.jsp?key1=a&key2=b
   → /app.jsp+(key1=a&key2=b)
http://127.0.0.1:8080/app.jsp?key1=a
   → /app.jsp+(key1=a)
http://127.0.0.1:8080/app.jsp?key1=a&key2=
   → /app.jsp+(key1=a)
http://127.0.0.1:8080/app.jsp
   → /app.jsp

파라미터 값의 시작 일부만을 사용할 수도 있다.

url_additional_request_keys = key1:5

앞에서와 같이 설정하면 다음 코드가 반환하는 값을 애플리케이션 서비스 이름에 추가한다.

request.getParameter("key1").substring(0, 5)

일반적으로 URI와 파라미터 사이의 구분 문자는 [?]이다. 하지만 이동식 단말기를 위한 WAS 등에서는 다른 구분 문자를 사용하기도 한다. 제니퍼 에이전트의 uri_separator 옵션을 통해서 이를 명시적으로 설정할 수 있다.

uri_separator = ?

파일 업로드 요청(multipart/form-data)에는 url_additional_request_keys 옵션이 적용되지 않는다. 그리고 제니퍼 에이전트의 ignore_url_post_request_parsing_prefixes 옵션으로 특정 이름으로 시작하는 URI에 대해서 url_additional_request_keys 옵션이 적용되지 않도록 할 수 있다.

ignore_url_post_request_parsing_prefixes = /kesa.web,/insa/x_servlet

또한 파라미터의 값이 다국어이고, 서블릿 3.2 이상에서 javax.servlet.http.HttpServletRequest 객체의 setCharacterEncoding 메소드를 호출해서 다국어 처리를 하는 경우에는 애플리케이션 서비스 이름에 다국어가 올바르게 나타나지 않을 수 있다. 제니퍼 에이전트가 소스 코드에서 setCharacterEncoding 메소드가 호출되기 전에 파라미터 값을 획득하기 때문이다.

doGet(...) {
     request.setCharacterEncoding(” KSC5601” );
     ...
}

따라서 이 경우에는 제니퍼 에이전트의 request_set_character_encoding 옵션으로 인코딩을 설정하도록 한다.

request_set_character_encoding = KSC5601

그리고 아쿠아 로직 등의 솔루션은 URI에 사용자 정보 등이 포함된다. 다음은 아쿠아 로직의 URI 예제이다.

/x/gate/user_123_01_21/http;//ap1/xx

이 URI를 그대로 애플리케이션 서비스 이름으로 사용하면 애플리케이션 서비스 이름이 사용자 수에 비례해서 크게 증가한다. 예를 들어, 애플리케이션이 1,000개이고 사용자가 1,000명인 경우에 애플리케이션 서비스 이름은 100만개가 된다. 이 결과로 제니퍼 서버에서 java.lang.OutOfMemoryError 예외가 발생할 수 있다.

이를 해결하기 위해서 제니퍼 에이전트의 uri_starter 옵션으로 URI의 특정 패턴을 시작점으로 애플리케이션 서비스 이름을 도출할 수 있다.

uri_starter = /http

앞의 예에서, 제니퍼 에이전트의 uri_starter 옵션을 /http로 설정하면 애플리케이션 서비스 이름은 다음과 같이 된다.

/http;//ap1/xx

일반 자바 애플리케이션

기본적으로 애플리케이션 서비스 이름은 클래스 이름과 메소드 이름으로 구성된다. 제니퍼 에이전트의 tx_server_ntype 옵션을 통해서 이를 다양하게 설정할 수 있다. 기본 값은 FULL이고, SIMPLE, CLASS, METHOD 등으로 설정할 수 있다. 수정한 tx_server_ntype 옵션을 반영하려면 제니퍼 에이전트를 설치한 자바 애플리케이션을 재시작해야 한다.

tx_server_ntype = FULL

예를 들어, pkg.ClassB 클래스의 process 메소드를 애플리케이션 서비스 시작점이라고 할 때 tx_server_ntype 옵션 설정에 따라서 애플리케이션 서비스 이름은 다음과 같이 결정된다.

그리고 애플리케이션 서비스 시작점인 메소드의 파라미터 값을 애플리케이션 서비스 이름으로 사용할 수도 있다. 이를 위해서는 제니퍼 에이전트의 tx_server_using_param 옵션을 true로 설정한다. 수정한 tx_server_using_param 옵션을 반영하려면 제니퍼 에이전트를 설치한 자바 애플리케이션을 재시작해야 한다.

tx_server_using_param = true

tx_server_using_param 옵션을 true로 설정하면, 애플리케이션 서비스 시작점인 메소드의 여러 개의 파라미터 중에서 java.lang.String 타입의 파라미터 중에서 첫번째 파라미터가 애플리케이션 서비스 이름이 된다. 해당 사항이 없는 경우에는 tx_server_ntype 옵션에 따라서 애플리케이션 서비스 이름이 결정된다.

그리고 애플리케이션 서비스 이름으로 애플리케이션 서비스 시작 메소드 내부에서 호출되는 특정 클래스의 특정 메소드의 파라미터나 반환 값을 사용할 수도 있다.

애플리케이션 서비스 시작 메소드 내부에서의 특정 클래스의 특정 메소드의 파라미터를 애플리케이션 서비스 이름으로 사용하려면 다음과 같이 설정한다. 수정한lwst_txserver_method_using_param 옵션을 반영하려면 제니퍼 에이전트를 설치한 자바 애플리케이션을 재시작해야 한다.

lwst_txserver_method_using_param = pkg.ClassC.f1(String)

이 경우에는 여러 개의 파라미터 중에서 java.lang.String 타입의 파라미터 중에서 첫번째 파라미터가 애플리케이션 서비스 이름이 된다.

그리고 애플리케이션 서비스 시작 메소드 내부에서의 특정 클래스의 특정 메소드의 반환값을 애플리케이션 서비스 이름으로 사용하려면 다음과 같이 설정한다. 수정한 lwst_txserver_method_using_return 옵션을 반영하려면 제니퍼 에이전트를 설치한 자바 애플리케이션을 재시작해야 한다.

lwst_txserver_method_using_return = pkg.ClassC.f2(String)

단, 이 경우에는 반환되는 객체의 유형이 java.lang.String이어야 한다.

lwst_txserver_method_using_param과 lwst_txserver_method_using_return 옵션에도 2개 이상은 [;]을 구분자로 해서 설정한다.

여러 옵션이 설정된 경우에는 다음 옵션 순서대로 애플리케이션 서비스 이름이 결정된다.

lwst_txserver_method_using_param과 lwst_txserver_method_using_return 옵션의 경우에는 실제 트랜잭션이 처리되는 과정에서 마지막으로 수행되는 메소드의 파리미터 혹은 반환 값이 애플리케이션 서비스 이름이 된다.

로직 기반 네이밍

애플리케이션 서비스 시작점에서 그 이름을 결정할 수 없는 경우가 있다. 예를 들어, SOAP 프로토콜을 사용하는 경우에 애플리케이션 서비스 시작점에서 XML을 파싱하지 않고는 그 이름을 판별하지 못할 수 있다. 이 경우에는 트랜잭션이 수행되는 로직 흐름에서 tx_naming으로 시작하는 옵션으로 설정한 클래스와 메소드 이름을 애플리케이션 서비스 이름에 추가할 수 있다. 수정한 tx_naming으로 시작하는 옵션을 반영하려면 제니퍼 에이전트를 설치한 자바 애플리케이션을 재시작해야 한다.

예를 들어, 애플리케이션 서비스 이름을 결정하는데 중요한 특정 클래스가 example.BizAction이라고 가정하자. 이를 애플리케이션 서비스 이름에 추가하려면 제니퍼 에이전트의 tx_naming_class 옵션으로 설정한다.

tx_naming_class = example.BizAction

그리고 example.LogAction도 애플리케이션 서비스 이름을 결정하는데 중요한 클래스라고 가정하자. 이 클래스도 애플리케이션 서비스 이름에 추가하려면 [;]을 구분자로 tx_naming_class 옵션에 설정한다. tx_naming_class 옵션뿐만 아니라 애플리케이션 서비스 이름과 관련한 모든 옵션에 2개 이상을 설정하려면 [;]을 구분자로 사용한다.

tx_naming_class = example.BizAction;example.LogAction

그런데 애플리케이션 서비스 이름에 추가되는 것은 특정 클래스의 특정 메소드 이름이다. 물론 이는 제니퍼 에이전트의 tx_naming_ntype 옵션 설정에 영향을 받는다. 따라서 앞에서와 같이 설정하면 트랜잭션 처리 과정에서 호출된 example.BizAction 클래스의 모든 메소드가 애플리케이션 서비스 이름에 추가된다.

따라서 특정 메소드만을 애플리케이션 서비스 이름에 추가하려면 제니퍼 에이전트의 tx_naming_target_method 옵션으로 설정한다.

tx_naming_target_method = process

그런데 애플리케이션 서비스 이름에 추가할 클래스들 중에서 이름이 동일한 메소드가 있고, 이중 특정 클래스의 특정 메소드만을 애플리케이션 서비스 이름에 추가하려면 다음과같이 구체적으로 설정한다.

tx_naming_target_method = example.BizAction.process

반대로 특정 메소드만을 애플리케이션 서비스 이름에 추가하지 않으려면 제니퍼 에이전트의 tx_naming_ignore_method 옵션으로 설정한다.

tx_naming_ignore_method = example.BizAction.someMethod

메소드의 접근자를 통해서도 애플리케이션 서비스 이름에 추가할 메소드를 설정할 수 있다. 예를 들어 public 접근자와 접근자가 없는 메소드를 애플리케이션 서비스 이름에 추가하려면 다음과 같이 설정한다.

tx_naming_access_method = public;none

tx_naming_access_method 옵션에 설정이 가능한 값은 다음과 같다.

그리고 특정 클래스를 상속한 모든 클래스를 애플리케이션 서비스 이름에 추가하려면 제니퍼 에이전트의 tx_naming_super 옵션을 사용한다. 예를 들어, example.BaseAction을 상속한 모든 클래스를 애플리케이션 서비스 이름에 추가하려면 다음과 같이 설정한다.

tx_naming_super = example.BaseAction

그러나 이 경우에 직접적으로 상속받은 클래스만이 애플리케이션 서비스 이름에 추가된다. 예를 들어, A 클래스가 example.BaseAction 클래스를 상속하고 B 클래스가 A 클래스를 상속했다면, A 클래스는 애플리케이션 서비스 이름에 추가되지만 B 클래스는 애플리케이션 서비스 이름에 추가되지 않는다.

그리고 특정 인터페이스를 구현한 모든 클래스를 애플리케이션 서비스 이름에 추가하려면 제니퍼 에이전트의 tx_naming_interface 옵션을 사용한다. 예를 들어, example.IAction 인터페이스를 구현한 모든 클래스를 애플리케이션 서비스 이름에 추가하려면 다음과 같이 설정한다.

tx_naming_interface = example.IAction

그러나 이 경우에 직접적으로 구현한 클래스만이 애플리케이션 서비스 이름에 추가된다. 예를 들어, A 클래스가 example.IAction 인터페이스를 구현하고 B 클래스가 A 클래스를 상속했다면, A 클래스는 애플리케이션 서비스 이름에 추가되지만 B 클래스는 애플리케이션 서비스 이름에 추가되지 않는다.

그리고 클래스의 이름을 이용해서도 애플리케이션 서비스 이름에 추가될 클래스를 설정할 수 있다. 이 경우에는 제니퍼 에이전트의 tx_naming_prefix, tx_naming_postfix, tx_naming_ignore_prefix 옵션을 사용한다. 예를 들어, 이름이 example.action으로 시작하는 모든 클래스를 애플리케이션 서비스 이름에 추가하려면 다음과 같이 한다.

tx_naming_prefix = example.action

또한 이름이 Action으로 끝나는 모든 클래스를 애플리케이션 서비스 이름에 추가하려면 다음과 같이 한다.

tx_naming_postfix = Action

그리고 특정 이름으로 시작하는 클래스를 애플리케이션 서비스 이름에 추가하지 않으려면 제니퍼 에이전트의 tx_naming_ignore_prefix 옵션을 사용한다. 이 옵션은 다른 모든 옵션에 우선한다.

tx_naming_ignore_prefix =

기본적으로 tx_naming으로 시작하는 옵션 설정에 의해서 애플리케이션 서비스 이름에 추가되는 것은 클래스 이름과 메소드 이름이다. 제니퍼 에이전트의 tx_naming_ntype 옵션을 통해서 이를 다양하게 설정할 수 있다. 기본 값은 CLASS이고, FULL, SIMPLE,METHOD 등으로 설정할 수 있다.

tx_naming_ntype = CLASS

예를 들어, pkg.ClassB 클래스의 process 메소드를 애플리케이션 서비스 이름에 추가할때 tx_naming_ntype 옵션 설정에 따라서 애플리케이션 서비스 이름에 다음 내용이 추가된다.

그리고 클래스와 메소드 이름이 아닌 파라미터 값을 애플리케이션 서비스 이름에 추가할 수도 있다. 이를 위해서는 제니퍼 에이전트의 tx_naming_using_param 옵션을 true로 설정한다.

tx_naming_using_param = true

tx_naming_using_param 옵션을 true로 설정하면, 메소드의 여러 개의 파라미터 중에서 java.lang.String 타입의 파라미터 중에서 첫번째 파라미터가 애플리케이션 서비스 이름에 추가된다. 해당 사항이 없는 경우에는 tx_naming_ntype 옵션을 따른다.

또한 클래스와 메소드 이름이 아닌 반환 값을 애플리케이션 서비스 이름에 추가할 수도 있다. 이를 위해서는 제니퍼 에이전트의 tx_naming_using_return 옵션을 true로 설정한다

tx_naming_using_return = true

tx_naming_using_return 옵션을 true로 설정하면, 반환 값이 java.lang.String 타입이면 해당 값을 애플리케이션 서비스 이름에 추가하고, 그렇지 않은 경우에는 tx_naming_ntype 옵션을 따른다.

예를 들어, txn.jsp에서 다음 코드를 수행하고 있다고 가정하자.

<%
  example.BizAction bizAction = new example.BizAction();
  bizAction.process(request, response);

  example.LogAction logAction = new example.LogAction();
  logAction.process(request, response);
%>

그리고 tx_naming을 다음과 같이 설정한다.

tx_naming_postfix = Action
tx_naming_ntype = CLASS

그러면 애플리케이션 서비스 이름은 다음과 같다.

/txn.jsp+BizAction+LogAction

닷넷 애플리케이션 서비스와 트랜잭션

애플리케이션은 여러 개의 애플리케이션 서비스로 구성되어 있다. 애플리케이션 서비스는 고정된 개념이 아니고, 호출 건수와 응답 시간 등의 성능 데이터를 수집하는데 기준이 되는 통계 단위이다.

애플리케이션 서비스를 애플리케이션이라고도 한다. 그러나 이는 전체 프로그램을 의미하는 애플리케이션과는 다른 의미에서 사용된다. 그 차이는 전체 맥락 속에서 파악해야 한다

일반적으로 애플리케이션 서비스는 업무를 기준으로 한다. 예를 들어, 쇼핑몰 애플리케이션에서는 제품 목록 보기, 제품 상세 내역 보기, 장바구니에 담기, 주문, 결제 등이 애플리케이션 서비스가 될 수 있다. 그런데 하나의 업무가 세분화될 수 있고, 성능 관리 측면에서는 세부 단계 별로 성능 데이터를 수집하는 것이 바람직하기 때문에 애플리케이션 서비스가 업무 구분보다 더 세분화되는 경향이 있다.

일차적으로 웹 애플리케이션에서는 URI가 애플리케이션 서비스를 지칭하는 대표적인 방법이다.

/view.aspx
/order.aspx
/pay.asmx
/submitOrder.svc

그러나 모든 요청의 URI가 동일해서 요청 파라미터로 애플리케이션 서비스를 구분해야하는 경우도 있을 수 있다.

/service.aspx?action=view
/service.aspx?action=order
/service.aspx?action=pay

또한 웹 애플리케이션이 아닌 경우에는 특정 클래스의 특정 메서드로 애플리케이션 서비스를 구분해야 한다.

example.ViewManager 클래스의 view 메서드
example.OrderManager 클래스의 order 메서드
example.PayManager 클래스의 pay 메서드

애플리케이션 서비스 네이밍

애플리케이션 서비스 이름은 APPLS 테이블에 저장된다. 기본적으로 웹 애플리케이션은 URI가 애플리케이션 서비스 이름이 된다. 그런데 요청 파라미터 값이나 특정 메서드의 파라미터 혹은 반환 값 등을 이용해서 애플리케이션 서비스 이름을 설정할 수도 있다.

이렇게 애플리케이션 서비스 이름을 다양한 방식으로 설정하는 것을 애플리케이션 서비스 네이밍이라고 한다.

웹 애플리케이션

웹 애플리케이션은 요청 URI가 애플리케이션 서비스 이름이 된다. 그런데 웹 애플리케이션 프레임워크의 발전으로 애플리케이션 서비스가 URI만으로는 구분되지 않는 경우가 많아지고 있다. 이런 경우에는 요청 파라미터를 이용해서 애플리케이션 서비스 이름을 구체적으로 설정할 수 있다. 이를 위해서 제니퍼 에이전트의 url_additional_request_keys 옵션에 요청 파라미터 이름을 설정한다.

url_additional_request_keys = key1,key2

앞의 경우에는 다음 코드가 반환하는 파라미터 값을 사용해서 애플리케이션 서비스 이름을 결정한다.

HttpContext.Current.Request.Params.Get( “key1” );
HttpContext.Current.Request.Params.Get( “key2” );

예를 들어, 특정 요청에 대한 애플리케이션 서비스 이름은 다음과 같이 결정된다.

http://127.0.0.1:8080/app.aspx?key1=a&key2=b
→ /app.aspx+(key1=a&key2=b)
http://127.0.0.1:8080/app.aspx?key1=a
→ /app.aspx +(key1=a)
http://127.0.0.1:8080/app.aspx?key1=a&key2=
→ /app.aspx +(key1=a)
http://127.0.0.1:8080/app.aspx
→ /app.aspx

파라미터 값의 시작 일부만을 사용할 수도 있다.

url_additional_request_keys = key1:5

앞에서와 같이 설정하면 다음 코드가 반환하는 값을 애플리케이션 서비스 이름에 추가한다.

HttpContext.Current.Request.Params.Get("key1").Substring(0, 5)

일반적으로 URI와 파라미터 사이의 구분 문자는 [?]이다. 하지만 이동식 단말기를 위한 WAS 등에서는 다른 구분 문자를 사용하기도 한다. 제니퍼 에이전트의 uri_separator 옵션을 통해서 이를 명시적으로 설정할 수 있다.

uri_separator = ?

파일 업로드 요청(multipart/form-data)에는 url_additional_request_keys 옵션이 적용되지 않는다. 그리고 제니퍼 에이전트의 ignore_url_post_request_parsing_prefixes 옵션으로 특정 이름으로 시작하는 URI에 대해서 url_additional_request_keys 옵션이 적용되지 않도록 할 수 있다.

ignore_url_post_request_parsing_prefixes = /kesa.web,/insa/controller

그리고, ASP.NET의 경우 Cookie를 사용하지 않는 세션 키를 지원하는 데 이를 사용하는 경우에는 요청 URI 형식에 세션 키 값이 포함된다. 다음은 세션 키가 포함된 URL 예제이다.

http://server/(session_key)/SessionState.aspx
예) http://localhost/(lit3py55t21z5v55vlm25s55)/Application/
SessionState.aspx

이 URI를 그대로 애플리케이션 서비스 이름으로 사용하면 애플리케이션 서비스 이름이 사용자 수에 비례해서 크게 증가한다. 예를 들어, 애플리케이션이 1,000개이고 사용자가 1,000명인 경우에 애플리케이션 서비스 이름은 100만개가 된다. 이 결과로 제니퍼 서버에서 java.lang.OutOfMemoryError 예외가 발생할 수 있다.

이를 해결하기 위해서 제니퍼 에이전트의 uri_starter 옵션으로 URI의 특정 패턴을 시작점으로 애플리케이션 서비스 이름을 도출할 수 있다. 앞의 예제를 위해서는 아래와 같이 설정하면,

uri_starter = )/

애플리케이션 서비스이름은 다음과 같이 된다.

)/Application/SessionState.aspx

애플리케이션 서비스 모니터링

제니퍼는 자바 애플리케이션을 모니터링 할 때 2가지 관점에서 성능 데이터를 수집한다. 하나는 트랜잭션별 성능 모니터링이고 다른 하나는 서비스별 성능 모니터링이다.

트랜잭션별 성능 모니터링은 클라이언트 요청에 대한 처리 현황을 각 트랜잭션별로 모니터링 하는 것으로 X-View를 이용한다. 자세한 사항은 X-View와 트렌잭션을 참조한다.

서비스별 성능 모니터링은 단위(10분) 시간 동안 수행되었던 트랜잭션들을 애플리케이션 서비스 단위로 통계화한 모니터링이다. 자세한 사항은 [실시간 모니터링 - 애플리케이션]과 [통계 분석 - 애플리케이션]을 참조한다.

호출 건수

호출 건수는 자바 애플리케이션의 전체 트랜잭션 처리 건수를 의미한다. 호출 건수는 일반 성능 데이터로 5분 동안의 호출 건수가 PERF_X_01~31 테이블의 HIT 칼럼에 저장되고, 특정 날짜의 호출 건수 변화 추이는 막대 차트를 통해서 확인할 수 있다.

금일 시간당 호출 건수

트랜잭션별 호출 건수, 평균 응답 시간 등의 성능 데이터를 애플리케이션 처리 현황 통계데이터라고 한다. 자세한 사항은 [성능 현황과 보고서]를 참조한다. 그리고 개별 트랜잭션에 대한 자세한 분석은 X-View를 통해서 이루어진다. 자세한 사항은 [X-View와 프로파일링]를 참조한다.

서비스 요청률과 서비스 처리율

서비스 요청률은 자바 애플리케이션의 1초당 트랜잭션 시작 건수를 의미하고, 서비스 처리율은 자바 애플리케이션의 1초당 트랜잭션 종료 건수를 의미한다.

대부분의 경우에는 서비스 요청률과 서비스 처리율이 비슷한 수치를 보이지만 호출 건수가 많거나 성능 저하가 발생하는 경우에는 서비스 요청률과 서비스 처리율의 차이가 클 수 있다.

서비스 요청률과 서비스 처리율은 제니퍼 에이전트가 수집하는 일반 성능 데이터로 실시간 30초 평균 값을 스피드 바, 스피드 미터, 런타임 라인 차트를 통해서 확인할 수 있다.

최근 서비스 요청율

또한 서비스 요청률과 서비스 처리율에 대한 5분 평균 값은 PERF_X_01~31 테이블의 ARRIVAL_RATE 칼럼과 SERVICE_RATE 칼럼에 저장되고, 특정 날짜의 서비스 요청률과 서비스 처리율의 변화 추이는 라인 차트를 통해서 확인할 수 있다.

금일 서비스 요청률

평균 응답 시간

평균 응답 시간은 전체 트랜잭션의 응답 시간의 합을 호출 건수로 나눈 것으로 단위는 초이다.

평균 응답 시간은 제니퍼 에이전트가 수집하는 일반 성능 데이터로 실시간 30초 평균 값을 런타임 라인 차트를 통해서 확인할 수 있다.

최근 평균 응답 시간

또한 평균 응답 시간에 대한 5분 평균 값은 PERF_X_01~31 테이블의 RESPONSE_TIME 칼럼에 저장되고, 특정 날짜의 평균 응답 시간의 변화 추이는 라인 차트를 통해서 확인할 수 있다.

금일 평균 응답 시간

트랜잭션과 예외 처리

트랜잭션 처리 과정에서 발생한 예외를 감지하고 수집하는 것은 서비스 모니터링에서 중요한 영역을 차지한다. 그런데 트랜잭션이 수행하면서 발생한 모든 예외를 감지하고 추적하면 전체 애플리케이션 성능에 부정적인 영향을 미칠 수 있다. 따라서 제니퍼는 핵심적인 예외만을 감지하고 처리한다.

제니퍼가 예외를 감지하고 수집하는 경우는 다음과 같다.

앞의 경우를 제외하고 트랜잭션 처리 과정에서 발생한 예외를 catch 문을 통해서 처리했다면 제니퍼는 이를 예외로 감지하지 않는다.

트랜잭션 성공과 실패

트랜잭션 종료시에 다음 예외가 감지되면 트랜잭션이 실패한 것으로 간주한다.

단순한 응답 시간 지연으로 예외가 발생해도, 트랜잭션 자체는 성공한 것으로 간주한다. 또한 외부 트랜잭션과 DB 처리 과정에서 예외가 발생해도 코드 상에서 catch 문으로 처리를 했다면 트랜잭션 자체는 성공한 것으로 간주한다

외부 트랜잭션과 예외

트랜잭션 처리 과정에서 감지할 수 있는 외부 트랜잭션 관련 예외는 다음과 같다.

JDBC 처리와 예외

트랜잭션 처리 과정에서 감지할 수 있는 JDBC 관련 예외는 다음과 같다.

임의의 예외 감지

트랜잭션 처리 과정에서 발생한 임의의 예외가 catch 문으로 처리가 되더라도 CustomTrace 어뎁터를 이용해서 이를 감지할 수 있다. 자세한 사항은 Customtrace 어텝터를참조한다.

CustomTrace 어뎁터로 예외를 감지하더라도 해당 트랜잭션은 성공한 것으로 간주한다.

서비스 모니터링과 예외 발생

응답 시간 지연

트랜잭션의 응답 시간이 임계치를 초과하면 WARNING_APP_BAD_RESPONSE 예외가 발생한다. 임계치는 제니퍼 에이전트의 app_bad_responsetime 옵션으로 설정한다. 기본값은 30000이고 단위는 밀리 세컨드이다.

app_bad_responsetime = 30000

서비스 무한 재귀 호출 감지

자바 애플리케이션에서 서블릿 혹은 JSP가 임계치(기본 값은 50,000)를 초과하여 다른 서블릿 혹은 JSP를 계속 호출하면 ERROR_RECURRSIVE_CALL 예외가 발생한다. 제니퍼 에이전트의 recurrsive_call_max_count 옵션을 통해서 임계치를 설정한다.

recurrsive_call_max_count = 50000

서블릿 혹은 JSP가 다른 서블릿 혹은 JSP를 호출한다는 것은 자바 코드 상에서 javax.servelt.RequestDispatcher 객체의 forward 혹은 include 메소드를 호출하는 것을 의미한다.

이 예외의 원인을 파악하기 위해서 제니퍼 에이전트 로그 파일에 관련 스택트레이스를 기록하려면, 제니퍼 에이전트의 recurrsive_call_trace 옵션을 true로 지정한다. 기본 값은 false이다.

recurrsive_call_trace = true

기본적으로 제니퍼 에이전트 로그 파일에 기록되는 스택트레이스 글자수를 10,000자로 제한한다. 제니퍼 에이전트의 recurrsive_call_trace_size 옵션을 통해서 글자 수를 설정할 수 있다.

recurrsive_call_trace_size = 10000

이 예외가 발생하면 해당 트랜잭션을 종료시킨다. 따라서 너무 작은 값을 recurrsive_call_max_count 옵션에 설정하면 서비스가 정상적으로 이루어지지 않을 수 있다.

액티브 서비스 모니터링

액티브 서비스는 자바 애플리케이션이 현재 처리 중인 트랜잭션을 의미한다. 즉 애플리케이션 시작점을 나타내는 메소드가 실행 중인 상태에 있는 트랜잭션을 액티브 서비스라고 한다.

액티브 서비스 개수

액티브 서비스 개수는 자바 애플리케이션이 현재 처리 중인 트랜잭션의 개수를 의미한다.

액티브 서비스 개수는 제니퍼 에이전트가 수집하는 일반 성능 데이터로 현재 값은 이퀄라이저 차트로, 실시간 30초 평균 값은 런타임 라인 차트를 통해서 확인할 수 있다.

실시간 액티브 서비스 개수

액티브 서비스 개수는 경과 시간 구간으로 구분되고, 이퀄라이저 차트는 경과 시간 구간을 색상별로 구분하여 표시한다. 다음은 경과 시간 구간에 대한 설명이다.

경과 시간 구간

경과 시간 구간

설명

0-1

경과 시간이 1초 미만인 경우

1-3

경과 시간이 1초 이상 3초 미만인 경우

3-8

경과 시간이 3초 이상 8초 미만인 경우

8-

경과 시간이 8초 이상인 경우

이 구간은 제니퍼 에이전트와 제니퍼 서버의 active_graph_interval 옵션으로 설정한다. 단위는 밀리 세컨드이다.

active_graph_interval = 0,1000,3000,8000

이 옵션을 변경하려면 제니퍼 에이전트와 제니퍼 서버의 옵션을 함께 수정해야 한다.

기본적으로 8초 이상인 경우가 이퀄라이저 차트의 하단에 나타난다. 이를 맨 상단에 표시하려면 제니퍼 서버의 ui_active_service_reverse 옵션을 true로 설정한다.

ui_active_service_reverse = true

이 옵션을 수정한 경우에는 로그인을 다시해야 한다.

또한 액티브 서비스 개수에 대한 5분 평균 값은 PERF_X_01~31 테이블의 ACTIVE_SERVICE 칼럼에 저장되고, 특정 날짜의 액티브 서비스 개수 변화 추이는 라인차트를 통해서 확인할 수 있다.

금일 액티브 서비스 개수

액티브 서비스 모니터링과 경보 발령

제니퍼 서버가 모니터링하는 모든 자바 애플리케이션의 5 초 동안의 액티브 서비스 개수의 합이 임계치(기본 값은 70 개)를 초과하면 ERROR_SERVICE_QUEUING 경보를 발령한다. 임계치는 제니퍼 서버의 active_service_alert_limit 옵션을 통해서 설정한다.

active_service_alert_limit = 70

액티브 서비스 중단하기

제니퍼는 트랜잭션을 처리하는 자바 쓰레드가 비정상적인 상태(wait 혹은 sleep 등)에서 멈추어 있는 경우에 해당 쓰레드를 중단시키는 기능을 제공한다. 비정상적으로 장시간 수행되는 트랜잭션을 중단해야 하는 이유는 멈추어 있는 쓰레드가 점유한 한정된 자원을 해제하기 위함이다. 반대로 이야기 하면 특별히 부족한 자원이 없는 경우에는 해당 쓰레드를 강제로 종료할 필요가 없다.

액티브 서비스 목록에서 장시간 수행중인 트랜잭션의 애플리케이션 이름을 클릭하면 다음과 같은 팝업 창이 나타난다.

액티브 서비스 상세

바로 이 액티브 서비스 팝업 창에서 트랜잭션을 처리하는 쓰레드를 제어할 수 있다. 즉 쓰레드를 일시 정지(suspend) 혹은 정지(stop)시킬 수 있다. 사용자가 속한 그룹이 killtrhead 권한을 가지고 있는 경우에만 해당 버튼들이 나타난다.

트랜잭션을 처리하는 쓰레드가 Socket Read 상태에서 멈추어 있으면 Socket Read 상태가 해제되기 전까지 쓰레드가 중단되지 않는다.


WAS에 따라서는 예측할 수 없는 부작용이 발생할 수 있다. 웹로직 8.x/9.x, 웹스피어4.x/5.x/6.x, 톰켓 5.x 등에서 테스트가 되었다.

경과 시간이 지연된 액티브 서비스 자동 종료

경과 시간이 임계치를 초과해서 장시간 지연되는 경우에는 액티브 서비스를 자동으로 종료할 수 있다. 이를 위해서는 제니퍼 에이전트의 enable_long_running_thread_auto_kill 옵션을 true로 설정한다.

enable_long_running_thread_auto_kill = true

임계치는 제니퍼 에이전트의 long_running_thread_auto_kill_timeout 옵션으로 설정한다. 단위는 밀리 세컨드이다.

액티브 파라미터

[실시간 모니터링 | 애플리케이션] 메뉴에서 액티브 서비스 목록을 확인할 때 애플리케이션 서비스 이름에 HTTP 파라미터 값을 추가해서 확인할 수 있다.

화면에서만 애플리케이션 서비스 이름에 HTTP 파라미터 값을 추가할 뿐 실제로 애플리케이션 서비스 이름을 변경하는 것은 아니다.

이를 위해서 애플리케이션 서비스 이름에 추가해서 보여줄 파라미터 이름을 제니퍼 에이전트의 http_post_request_tracking_list 옵션으로 설정한다.

http_post_request_tracking_list = txid

그리고 액티브 서비스 목록에 나타나는 애플리케이션 서비스 이름에 트랜잭션을 처리하는 과정에서 호출한 특정 클래스의 특정 메소드의 첫번째 java.lang.String 유형의 파라미터를 애플리케이션 서비스 이름에 추가해서 보여줄 수 있다. 수정한 active_param으로 시작하는 옵션을 반영하려면 제니퍼 에이전트를 설치한 자바 애플리케이션을 재시작해야한다.

기본적으로 java.lang.String 유형의 첫번째 파라미터 값을 애플리케이션 서비스 이름에 추가한다. 그런데 byte[] 유형의 첫번째 파라미터 값을 애플리케이션 서비스 이름에 추가하려면 제니퍼 에이전트의 active_param_type 옵션을 byte[]로 설정한다. 기본 값은java.lang.String이다.

active_param_type = byte[]

예를 들어, 애플리케이션 서비스 이름에 example.BizAction 클래스의 모든 메소드의 파라미터 값을 추가하려면 제니퍼 에이전트의 active_param_class 옵션으로 설정한다.

active_param_class = example.BizAction

그리고 example.LogAction 클래스의 모든 메소드의 파라미터 값을 애플리케이션 서비스이름에 추가하려면 [;]을 구분자로 active_param_class 옵션에 설정한다. active_param_class 옵션뿐만 아니라 애플리케이션 서비스 이름과 관련한 모든 옵션에 2개 이상을 설정하려면 [;]을 구분자로 사용한다.

active_param_class = example.BizAction;example.LogAction

특정 메소드의 파라미터 값만을 애플리케이션 서비스 이름에 추가하려면 제니퍼 에이전트의 active_param_target_method 옵션으로 설정한다.

active_param_target_method = process

그런데 애플리케이션 서비스 이름에 추가할 클래스들 중에서 이름이 동일한 메소드가 있고, 이중 특정 클래스의 특정 메소드의 파라미터 값만을 애플리케이션 서비스 이름에 추가하려면 다음과 같이 구체적으로 설정한다.

active_param_target_method = example.BizAction.process

반대로 특정 메소드의 파라미터 값만을 애플리케이션 서비스 이름에 추가하지 않으려면 제니퍼 에이전트의 active_param_ignore_method 옵션으로 설정한다.

active_param_ignore_method = example.BizAction.someMethod

메소드의 접근자를 통해서도 애플리케이션 서비스 이름에 추가할 메소드의 파라미터 값을 설정할 수 있다. 예를 들어 public 접근자와 접근자가 없는 메소드의 파라미터 값을 애플리케이션 서비스 이름에 추가하려면 다음과 같이 설정한다.

active_param_access_method = public;none

active_param_access_method 옵션에 설정이 가능한 값은 다음과 같다.

그리고 특정 클래스를 상속한 모든 클래스의 메소드의 파라미터 값을 애플리케이션 서비스 이름에 추가하려면 제니퍼 에이전트의 active_param_super 옵션을 사용한다. 예를 들어, example.BaseAction을 상속한 모든 클래스의 모든 메소드의 파라미터 값을 애플리케이션 서비스 이름에 추가하려면 다음과 같이 설정한다.

active_param_super = example.BaseAction

그러나 이 경우에 직접적으로 상속받은 클래스의 메소드의 파라미터 값만이 애플리케이션 서비스 이름에 추가된다. 예를 들어, A 클래스가 example.BaseAction 클래스를 상속하고 B 클래스가 A 클래스를 상속했다면, A 클래스의 메소드의 파라미터 값은 애플리케이션 서비스 이름에 추가되지만 B 클래스의 메소드의 파라미터 값은 애플리케이션 서비스 이름에 추가되지 않는다.

그리고 특정 인터페이스를 구현한 모든 클래스의 메소드의 파라미터 값을 애플리케이션 서비스 이름에 추가하려면 제니퍼 에이전트의 active_param_interface 옵션을 사용한다. 예를 들어, example.IAction 인터페이스를 구현한 모든 클래스의 메소드의 파라미터 값을 애플리케이션 서비스 이름에 추가하려면 다음과 같이 설정한다.

active_param_interface = example.IAction

그러나 이 경우에 직접적으로 구현한 클래스의 메소드의 파라미터 값만이 애플리케이션 서비스 이름에 추가된다. 예를 들어, A 클래스가 example.IAction 인터페이스를 구현하고 B 클래스가 A 클래스를 상속했다면, A 클래스의 메소드의 파라미터 값은 애플리케이션 서비스 이름에 추가되지만 B 클래스의 메소드의 파라미터 값은 애플리케이션 서비스 이름에 추가되지 않는다.

그리고 클래스의 이름을 이용해서도 애플리케이션 서비스 이름에 추가될 클래스의 메소드의 파라미터 값을 설정할 수 있다. 이 경우에는 제니퍼 에이전트의 active_param_prefix, active_param_postfix, active_param_ignore_prefix 옵션을 사용한다. 예를 들어, 이름이 example.action으로 시작하는 모든 클래스의 메소드의 파라미터 값을 애플리케이션 서비스 이름에 추가하려면 다음과 같이 한다.

active_param_prefix = example.action

또한 이름이 Action으로 끝나는 모든 클래스의 메소드의 파라미터 값을 애플리케이션 서비스 이름에 추가하려면 다음과 같이 한다.

active_param_postfix = Action

그리고 특정 이름으로 시작하는 클래스의 메소드의 파라미터 값을 애플리케이션 서비스 이름에 추가하지 않으려면 제니퍼 에이전트의 active_param_ignore_prefix 옵션을 사용한다. 이 옵션은 다른 모든 옵션에 우선한다.

active_param_ignore_prefix =

액티브 스택트레이스

액티브 스택트레이스는 액티브 서비스의 스택트레이스를 추출하는 기능이다. X-View 프로파일 데이터와 유사하지만 X-View 프로파일 데이터는 영구적으로 저장되어 트랜잭션이 종료한 후에도 조회할 수 있는 반면에, 액티브 스택트레이스는 휘발성 데이터로 트랜잭션이 종료하면 사라진다.

액티브 스택트레이스와 X-View 프로파일 데이터

액티브 스택트레이스는 다음과 같이 액티브 서비스 상세 정보를 보여주는 팝업 창에서 확인할 수 있다.

액티브 스택트레이스

그러나 트랜잭션을 처리하는 과정에서 호출한 모든 메소드를 스택트레이스로 보여주지는 않는다. 제니퍼 에이전트의 stacktrace 시작하는 옵션으로 설정한 클래스의 메소드만이 스택트레이스에 포함된다. 수정한 stacktrace으로 시작하는 옵션을 반영하려면 제니퍼 에이전트를 설치한 자바 애플리케이션을 재시작해야 한다.

예를 들어, example.BizAction 클래스의 모든 메소드를 스택트레이스에 포함시키려면 제니퍼 에이전트의 stacktrace_class 옵션으로 설정한다.

stacktrace_class = example.BizAction

그리고 example.LogAction 클래스의 모든 메소드도 스택트레이스에 포함시키려면 [;]을 구분자로 stacktrace_class 옵션에 설정한다. stacktrace_class 옵션뿐만 아니라 스택트레이스와 관련한 모든 옵션에 2개 이상을 설정하려면 [;]을 구분자로 사용한다.

stacktrace_class = example.BizAction;example.LogAction

메소드의 접근자를 통해서도 스택트레이스에 포함시킬 메소드를 설정할 수 있다. 예를 들어, public 접근자와 접근자가 없는 메소드만을 스택트레이스에 포함시키려면 다음과 같이 설정한다.

stacktrace_access_method = public;none

stacktrace_access_method 옵션에 설정이 가능한 값은 다음과 같다.

그리고 특정 클래스를 상속한 모든 클래스의 메소드를 스택트레이스에 포함시키려면 제니퍼 에이전트의 stacktrace_super 옵션을 사용한다. 예를 들어, example.BaseAction을 상속한 모든 클래스의 메소드를 스택트레이스에 포함시키려면 다음과 같이 설정한다.

stacktrace_super = example.BaseAction

그러나 이 경우에 직접적으로 상속받은 클래스의 메소드만을 스택트레이스에 포함시킨다. 예를 들어, A 클래스가 example.BaseAction 클래스를 상속하고 B 클래스가 A 클래스를 상속했다면, A 클래스의 메소드는 스택트레이스에 포함시키지만 B 클래스의 메소드는 스택트레이스에 포함시키지 않는다.

그리고 특정 인터페이스를 구현한 모든 클래스의 메소드를 스택트레이스에 포함시키려면 제니퍼 에이전트의 stacktrace_interface 옵션을 사용한다. 예를 들어, example.IAction 인터페이스를 구현한 모든 클래스의 메소드를 스택트레이스에 포함시키려면 다음과 같이 설정한다.

stacktrace_interface = example.IAction

그러나 이 경우에 직접적으로 구현한 클래스의 메소드만을 스택트레이스에 포함시킨다. 예를 들어, A 클래스가 example.IAction 인터페이스를 구현하고 B 클래스가 A 클래스를 상속했다면, A 클래스의 메소드는 스택트레이스에 포함시키지만 B 클래스의 메소드는 스택트레이스에 포함시키지 않는다.

그리고 클래스의 이름을 이용해서도 스택트레이스에 포함될 클래스의 메소드를 설정할 수 있다. 이 경우에는 제니퍼 에이전트의 stacktrace_prefix, stacktrace_postfix 옵션을 사용한다. 예를 들어, 이름이 example.action으로 시작하는 모든 클래스의 메소드를 스택트레이스에 추가시키려면 다음과 같이 한다.

stacktrace_prefix = example.action

또한 이름이 Action으로 끝나는 모든 클래스의 메소드를 스택트레이스에 추가시키려면 다음과 같이 한다.

stacktrace_postfix = Action

마지막으로 제니퍼 에이전트의 stacktrace_stacksize 옵션으로 스택트레이스에 포함시킬 메소드의 개수를 설정할 수 있다. 기본 값은 300이다.

stacktrace_stacksize = 300

액티브 프로파일

액티브 서비스의 액티브한 X-View 프로파일 데이터를 다음과 같이 액티브 서비스 상세 정보를 보여주는 팝업 창에서 확인할 수 있다.

액티브 프로파일

화면에 나타날 X-View 프로파일 데이터의 프로파일 항목 개수를 제니퍼 서버의 active_profile_max_line 옵션으로 설정할 수 있다.

active_profile_max_line = 50

부하량 제어(PLC)

PLC(Peak Load Control)는 액티브 서비스 개수와 비즈니스 중요 그룹 및 성능 저하 그룹을 기준으로 부하량 폭주를 조절하는 기능이다.

PLC 기본 설정

우선 PLC를 사용하려면 제니퍼 에이전트의 set_limit_active_service 옵션을 true로 설정한다.

set_limit_active_service = true

PLC를 사용하면 액티브 서비스 개수가 제니퍼 에이전트의 max_num_of_active_service 옵션으로 설정한 임계치를 초과하는 경우에 서비스 큐잉 현상을 방지하기 위해서 추가적인 요청을 거절한다.

max_num_of_active_service = 100

PLC에 의해 서비스 요청이 거절되면 부하량이 특정 임계치를 초과하여 추가적인 요청을 처리할 수 없음을 자바 애플리케이션 사용자에게 공지해야 한다. 공지 방법에는 두가지가 있으며 제니퍼 에이전트의 request_reject_type 옵션으로 공지 방법을 설정한다.

request_reject_type = [message|redirect]

request_reject_type 옵션으로 message를 설정하면 제니퍼 에이전트의 request_reject_message 옵션에 설정한 텍스트를 사용자에게 보여준다.

request_reject_message = Workload so high. Please, try again later!

request_reject_type 옵션으로 redirect를 설정하면 제니퍼 에이전트의 request_reject_redirect_url 옵션으로 설정한 페이지를 사용자에게 보여준다.

request_reject_redirect_url = /error.html

request_reject_redirect_url 옵션으로 지정한 페이지가 PLC에 의해서 재귀적으로 거절되는 현상을 방지하기 위해서 request_reject_redirect_url 옵션에 HTML 페이지를 지정하는 것을 권장한다.

PLC 그룹 설정

비즈니스 중요도 및 성능 저하에 미치는 영향을 기준으로, 애플리케이션을 분류하여 해당 애플리케이션 그룹 별로 PLC 설정을 다르게 적용할 수 있다.

비즈니스 중요 그룹 지정

부하량이 증가할 때 자바 애플리케이션의 처리 역량을 업무 중요도에 따라서 다르게 분배할 수 있다. 즉, 비즈니스 중요 그룹 지정을 통해서 부하량이 증가할 때 중요하지 않은 업무보다 중요한 업무가 처리될 확률을 높일 수 있다.

비즈니스 중요 그룹은 다음과 같이 설정한다. 우선 제니퍼 에이전트의 biz_group.num 옵션으로 전체 비즈니스 중요 그룹에 대한 액티브 서비스 개수 임계치를 설정한다.

biz_group.num = 20

max_num_of_active_service 옵션은 전체 액티브 서비스 개수에 대한 임계치를 의미하고 biz_group.num 옵션은 전체 비즈니스 중요 그룹의 액티브 서비스 개수에 대한 임계치를 의미한다.

개별 비즈니스 중요 그룹은 제니퍼 에이전트의 biz_group.#.num 옵션과 biz_group.#.list 옵션으로 설정한다. # 대신에 임의의 비즈니스 중요 그룹 번호를 입력한다.

예를 들어, /biz1.jsp와 /biz.2.jsp를 비즈니스 중요 그룹으로 묶어 액티브 서비스 개수 임계치로 10을 지정하고, /biz3.jsp와 /biz4.jsp를 비즈니스 중요 그룹으로 묶어 액티브 서비스 개수 임계치로 15를 지정하려면 다음과 같이 설정한다.

biz_group.1.num = 10
biz_group.1.list = /biz1.jsp, /biz2.jsp
biz_group.2.num = 15
biz_group.2.list = /biz3.jsp, /biz4.jsp

최대 20개까지의 비즈니스 중요 그룹을 설정할 수 있다.

비즈니스 중요 그룹에 의한 PLC 처리 정책은 다음과 같다.

성능 저하 그룹 지정

성능 저하에 영향을 미치는 애플리케이션들을 성능 저하 그룹으로 지정하고 각각의 성능저하 그룹에 대한 액티브 서비스 개수 임계치를 설정하여 성능 저하를 유발하는 애플리케이션이 수행되는 개수를 제한할 수 있다.

성능 저하 그룹은 다음과 같이 설정한다. 우선 제니퍼 에이전트의 limit_group.num 옵션으로 전체 성능 저하 그룹에 대한 액티브 서비스 개수 임계치를 설정한다.

limit_group.num = 20

max_num_of_active_service 옵션은 전체 액티브 서비스 개수에 대한 임계치를 의미하고 limit_group.num 옵션은 전체 성능 저하 그룹의 액티브 서비스 개수에 대한 임계치를 의미한다.

개별 성능 저하 그룹은 제니퍼 에이전트의 limit_group.#.num 옵션과 limit_group.#.list 옵션으로 설정한다. # 대신에 임의의 성능 저하 그룹 번호를 입력한다. 예를 들어서 /bad1.jsp와 /bad.2.jsp를 성능 저하 그룹으로 묶어 액티브 서비스 개수 임계치로 10을 지정하고, /bad3.jsp와 /bad4.jsp를 성능 저하 그룹으로 묶어 액티브 서비스 개수 임계치로 15를 지정하려면 다음과 같이 설정한다.

limit_group.1.num = 10
limit_group.1.list = /bad1.jsp, /bad.jsp
limit_group.2.num = 15
limit_group.2.list = /bad.jsp, /bad.jsp

최대 20개까지의 성능 저하 그룹을 설정할 수 있다.

성능 저하 그룹에 의한 PLC 처리 정책은 다음과 같다.

애플리케이션 목록 설정

비즈니스 중요 그룹과 성능 저하 그룹에 속하는 애플리케이션 목록은 다음과 같이 애플리케이션 이름을 [,]로 구분하여 설정한다.

biz_group.1.list = /biz1.jsp, /biz2.jsp

그리고 애플리케이션 이름에 [*]를 사용할 수 있다.

애플리케이션 이름 설정

애플리케이션 이름

설명

/biz*

애플리케이션 이름이 /biz로 시작하는 모든 애플리케이션이 해당 그룹에 속한다.

*biz.jsp

애플리케이션 이름이 biz.jsp로 끝나는 모든 애플리케이션이 해당 그룹에 속한다.

*biz*

애플리케이션 이름에 biz가 들어가는 모든 애플리케이션이 해당 그룹에 속한다.

PLC 애플리케이션 목록에 제니퍼 에이전트의 tx_naming 옵션으로 설정한 애플리케이션 이름을 설정할 수는 없다.

PLC 동작 확인

사용자는 PLC 동작 여부를 제니퍼 서버를 통해서 확인할 수 있다.

첫번째로 PLC에 의해서 요청이 거절되면 ERROR_PLC_REJECTED 예외가 발생한다.

두번째로 스피드 미터를 통해서 PLC 동작을 확인할 수 있다. 정상적인 상황에서는 트랜잭션이 제니퍼 에이전트 기둥 가운데로 지나가지만 PLC에 의해서 요청이 거절되면 에이전트 기둥의 오른쪽 옆을 따라서 흐른다

스피드 미터를 통한 PLC 확인

CRUD 매트릭스

[통계 분석 | CRUD 매트릭스] 메뉴에서 애플리케이션 서비스와 데이터베이스 테이블 혹은 함수와의 상관 관계를 생성, 읽기, 삭제, 업데이트 등의 기준으로 확인할 수 있다.

프로젝트 분석 및 설계 단계에서 정의한 CRUD 매트릭스와 실제 운영 중에 나타난 CRUD 매트릭스의 비교 분석에 이 기능을 사용할 수 있다. 그래서 애플리케이션 품질을 관리하는데 이 기능을 유용하게 사용할 수 있다.

CRUD 매트릭스 조회는 다량의 데이터를 조회하기 때문에 시간이 많이 걸릴 수 있다.

CRUD 조회화면

테이블 입력 필드에 입력할 수 있는 검색 조건의 형식은 다음과 같다.

* - 모든 테이블에 대해서 검색을 한다.
*BIZ - 테이블의 이름이 BIZ로 끝나는 테이블에 대해서 검색을 한다.
*BIZ* - 테이블의 이름에 BIZ가 들어가는 테이블에 대해서 검색을 한다
BIZ* - 테이블의 이름이 BIZ로 시작하는 테이블에 대해서 검색을 한다.

테이블 이름뿐만 아니라 CRUD 형식에 따른 검색도 가능하다.

*(*) - 모든 CRUD 형식에 대해서 검색을 한다.
*(R) - R 형식에 대해서 검색을 한다. 이 조건은 CR, CRUD, RU, RD 등을 모두 포함한다.
*(C|R) - C 혹은 R 형식에 대해서 검색을 한다. |를 생략하고 *(CR)로 입력할 수도 있다.
*(C&U) - C와 U가 모두 있는 형식에 대해서 검색을 한다.
*(C&!R&!U&!D) - 오직 C만 있는 형식에 대해서 검색을 한다.

테이블 이름과 CRUD 형식을 함께 사용한 검색도 가능하다.

BIZ*(CUD) - 테이블 이름이 BIZ로 시작하는 테이블 중에서 C 혹은 U 혹은 D 형식에 대해서 검색을 한다.
*BIZ(D) - 테이블 이름이 BIZ로 끝나는 테이블 중에서 D 형식에 대해서 검색을 한다.
*BIZ*(R&!C&!U&!D) - 테이블 이름에 BIZ가 들어가는 테이블 중에서 오직 R만 있는 형식에 대해서 검색을 한다.

그런데 제니퍼 서버의 disable_app_mapping_db 옵션을 true로 설정한 경우에는 CRUD 매트릭스를 조회할 수 없다.

disable_app_mapping_db = true

서비스 덤프

자바 애플리케이션에 대한 실시간 성능 데이터와 액티브 서비스 목록 등의 데이터를 파일에 기록할 수 있다. 이를 서비스 덤프라고 한다.

사용자는 [장애진단 | 서비스 덤프] 메뉴에서 특정 제니퍼 에이전트에 대한 서비스 덤프를 기록할 수 있다.

서비스 덤프 파일이 기록되는 디렉토리는 제니퍼 에이전트의 jdump_dir 옵션으로 설정한다. 기본 디렉토리는 작업 디렉토리이다.

jdump_dir = ./

서비스 덤프

[덤프] 버튼을 클릭해도 서비스 덤프 파일 목록에 새로운 서비스 덤프 파일이 보이지 않을 수 있다. 이는 제니퍼 에이전트가 서비스 덤프 파일을 비동기적으로 기록하기 때문에 발생하는 현상이다. 따라서 몇 초 후에 서비스 덤프 파일 목록을 다시 확인하면 새로운 서비스 덤프 파일을 확인할 수 있을 것이다. 따라서 새로운 서비스 덤프 파일이 목록에 바로 나타나지 않는다고 [덤프] 버튼을 연속해서 클릭하지 않도록 한다.

서비스 덤프 파일은 제니퍼 서버가 아닌 제니퍼 에이전트의 작업 디렉토리에 기록된다.

서비스 덤프 파일 내용 보기

서비스 덤프 파일에는 다음 내용들이 기록된다.

서비스 덤프 파일 내용

자동 서비스 덤프 기록

액티브 서비스 개수가 지정된 임계치를 초과하면 자동으로 서비스 덤프를 기록하도록 할 수 있다. 이를 위해서는 제니퍼 에이전트의 enable_dump_triggering 옵션을 true로 설정한다.

enable_dump_triggering = true

그리고 액티브 서비스 개수 임계치는 제니퍼 에이전트의 number_of_dump_trigger 옵션으로 설정한다.

number_of_dump_trigger = 90

빈번한 서비스 덤프 기록을 방지하기 위해서 자동 서비스 덤프 기록 간격을 제니퍼 에이전트의 dump_trigger_sleep_interval 옵션으로 설정한다. 단위는 밀리 세컨드이다.

dump_trigger_sleep_interval = 180000

고급 서비스 모니터링

SOA(Service Oriented Architecture)와 같은 환경에서 서비스 모니터링을 하는 방법을 설명한다.

글로벌 트랜잭션 연계 추적

기본적으로 제니퍼는 하나의 자바 쓰레드가 처리하는 트랜잭션을 추적한다. 즉, 하나의 요청이 자바 애플리케이션에 전달되면 해당 요청을 처리하기 위한 작업 쓰레드가 배정되고, 이 쓰레드가 트랜잭션을 처음부터 끝 까지 처리한다. 그런데 EAI(Enterprise Application Integration) 혹은 ESB(Enterprise Service Bus)와 같은 SOA 환경에서는 하나의 요청이 2개 이상의 자바 쓰레드에 의해서 처리되거나, 여러 개의 자바 애플리케이션이 XML 웹서비스를 이용해서 하나의 요청을 처리하기도 한다.

즉, 하나의 요청이 동일 애플리케이션 혹은 여러 애플리케이션에서 다수의 트랜잭션으로 처리되는 것이다. 따라서 서비스 모니터링을 위해서 하나의 요청을 처리한 트랜잭션들의 연관 관계를 제공해줄 필요가 있다. 이를 위해서 제니퍼는 GUID(Globally Unique Identifier)를 사용한다.

제니퍼는 애플리케이션이 처리하는 모든 트랜잭션에 UUID(Universally Unique Identifier)를 부여해서 트랜잭션을 구별한다. 그런데 동일한 요청을 처리하는 트랜잭션들에는 별도 로 동일한 GUID를 부여해서 여러 개의 트랜잭션들의 상관 관계를 추적한다. 이를 글로벌트랜잭션 연계 추적 혹은 GUID 추적이라고 한다.

GUID 추적을 하려면 제니퍼 에이전트의 trace_related_transaction 옵션을 true로 설정해야 한다.

trace_related_transaction = true

그런데 UUID는 제니퍼가 생성하여 트랜잭션에 부여하지만, GUID는 제니퍼가 아닌 애플리케이션이 관리하고 생성하는 값이기 때문에 이 값을 찾아내서 트랜잭션에 부여해야 한다. 제니퍼는 이를 위한 다양한 방법을 제공한다.

우선 HTTP 해더 정보에서 GUID를 추출해서 이를 트랜잭션에 부여할 수 있다. 이를 위해서는 제니퍼 에이전트의 relatx_guid_keyname 옵션으로 GUID를 나타내는 HTTP 해더 키 이름을 설정한다.

relatx_guid_keyname = _J_GUID_

앞에서와 같이 설정하면 다음과 같은 코드를 수행하면서 트랜잭션에 GUID와 선행 트랜잭션의 UUID를 부여한다.

String guid = request.getHeader( “_J_GUID_” );

그리고 트랜잭션을 처리하는 과정에서 호출되는 임의의 클래스의 임의의 메소드의 파라미터를 GUID로 트랜잭션에 부여할 수도 있다.

제니퍼 에이전트의 guid_param 옵션으로 GUID를 추출할 클래스의 메소드를 설정한다. 이 때 메소드의 파라미터 까지 기술해야 한다. 단, 파라미터는 패키지는 이름을 제외한 클래스 이름만으로 설정할 수 있다. 예를 들어, example.Action 클래스의 process 메소드의 파라미터 값을 GUID로 트랜잭션에 부여하려면 다음과 같이 설정한다. 수정한 guid_param 옵션을 반영하려면 제니퍼 에이전트를 설치한 자바 애플리케이션을 재시작해야 한다.

guid_param = example.Action.process(String, String)

이 때 파라미터의 유형은 java.lang.String이거나 byte[]이어야 한다.

기본적으로 첫번째 파라미터 값을 GUID로 트랜잭션에 부여하는데 제니퍼 에이전트의 guid_param_index 옵션으로 GUID로 사용할 파라미터 값을 지정할 수 있다. 0으로 설정하면 첫번째 파라미터의 값, 1로 설정하면 두번째 파라미터의 값을 GUID로 트랜잭션에 부여한다.

guid_param_index = 1

그리고 제니퍼 에이전트의 guid_return 옵션으로 지정한 메소드가 반환하는 값을 GUID로 트랜잭션에 부여할 수도 있다. 이 때 메소드의 파라미터 까지 기술해야 한다. 단, 파라미터는 패키지는 이름을 제외한 클래스 이름만으로 설정할 수 있다. 예를 들어, example.Action 클래스의 execute 메소드의 반환 값을 GUID로 트랜잭션에 부여하려면 다음과 같이 설정한다. 수정한 guid_return 옵션을 반영하려면 제니퍼 에이전트를 설치한 자바 애플리케이션을 재시작해야 한다.

guid_return = example.Action.execute(String, String)

또한 GUID가 없는 경우에는 현재 트랜잭션의 UUID를 GUID로 부여하도록 설정할 수 있다. 이를 위해서는 제니퍼 에이전트의 enable_guid_from_tuid 옵션을 true로 설정한다.

enable_guid_from_tuid = true

GUID 추적과 관련한 트랜잭션은 X-View의 GUID 뷰에서 모니터링할 수있다. 자세한 사항은 [GUID]를 참조한다. 그리고 상세한 분석을 하려면 [XVLog를 통한 X-View 트랜잭션 데이터 처리]을 참조한다. 앞에서 설명한 내용으로 GUID를 부여할 수 없다면, 애플리케이션소스 코드를 수정해서 처리해야 한다. 이와 관련한 자세한 사항은 [ActiveTraceUtil]를 참조한다.

앞에서 설명한 내용으로 GUID를 부여할 수 없다면, 애플리케이션 소스 코드를 수정해서 처리해야 한다. 이와 관련한 자세한 사항은 Activetraceutil를 참조한다.

HTTP 해더와 파라미터 로깅

제니퍼 에이전트 로그 파일에 HTTP 해더와 파라미터 값을 기록하려면 제니퍼 에이전트의 dump_http_hide_all 옵션을 false로 설정한다. 기본 값은 true이다.

dump_http_hide_all = true

보안 등의 이유로 제니퍼 에이전트 로그 파일에 기록하지 않을 HTTP 해더와 파라미터 이름을 제니퍼 에이전트의 dump_http_hide_key 옵션으로 설정할 수 있다. 2개 이상은 콤마[,]를 구분자로 구분한다. 예를 들어, cookie를 이름으로 하는 HTTP 해더 값을 기록하지 않으려면 다음과 같이 설정한다.

dump_http_hide_key = cookie

HTTP 해더와 파라미터에 동시에 적용된다.

특정 URI에 대해서만 HTTP 해더를 제니퍼 에이전트 로그 파일에 기록하려면 제니퍼 에이전트의 dump_http_header_url_prefix 옵션으로 해당 URI를 설정한다. 다음과 같이 설정하면 모든 URI에 대해서 로그를 기록한다. 2개 이상은 콤마[,]를 구분자로 구분한다.

dump_http_header_url_prefix = /

파라미터에 대해서는 제니퍼 에이전트의 dump_http_parameter_url_prefix 옵션을 사용한다. 설정 방법은 dump_http_header_url_prefix 옵션과 동일하다.

사용자 모니터링

WAS에 기반한 웹 애플리케이션을 모니터링할 때는 액티브 사용자 수, 동시단말 사용자수, 방문자 수, 대기 시간 등의 데이터를 수집할 수 있다. 이를 사용자 모니터링이라고 한다.

쿠키를 이용한 사용자 모니터링

과거 클라이언트/서버 환경에서는 단순하게 TCP/IP 연결 개수를 접속자 수로 간주할 수 있었지만 웹 환경의 HTTP 프로토콜은 Connectionless이기 때문에 단순하게 TCP/IP 연결 개수를 접속자 수로 간주할 수 없다. 이 문제를 극복하기 위해서 제니퍼는 쿠키를 이용한 사용자 모니터링을 한다.

제니퍼 에이전트는 트랜잭션이 시작할 때 wmonid 쿠키의 존재 여부를 확인한다. 해당 쿠키가 존재하지 않으면 이 트랜잭션을 새로운 사용자에 의한 요청으로 간주하고 방문자 수를 증가시킨다. 그리고 임의의 값을 생성해서 wmonid 쿠키로 지정한다.

그리고 쿠키는 영구 쿠키이다. 그래서 웹 브라우저를 다시 시작해도 wmonid 쿠키가 유지되므로 방문자 수는 증가하지 않는다. 물론 방문자 수를 계산할 때 wmonid 뿐만 아니라 시간도 고려한다. 자세한 사항은 [방문자 수(128 페이지)]를 참조한다.

그런데 쿠키의 크기에는 제한이 있다. 따라서 웹 애플리케이션이 쿠키를 많이 사용하고 있다면, 제니퍼 에이전트가 wmonid 쿠키를 추가할 때 가능한 쿠키의 크기를 초과하면서 문제가 발생할 수 있다. 이 경우에는 제니퍼 에이전트의 hotfix_remote_address_for_wmonid 옵션을 true로 설정해서 쿠키를 이용한 사용자 모니터링을 비활성화시켜야 한다.

hotfix_remote_address_for_wmonid = true

hotfix_remote_address_for_wmonid 옵션을 true로 설정하면 쿠키가 아닌 클라이언트 IP로 사용자를 구분하기 때문에 동시단말 사용자 수와, 방문자 수 등의 데이터 정확도가 감소하게 된다.

그리고 도메인 이름으로 서비스하는 여러 개의 웹 애플리케이션을 모니터링할 때 고려해야 하는 것이 있다. 예를 들어, 2개의 웹 애플리케이션을 모니터링하고 있고, 각각의 도메인 이름은 다음과 같다고 가정한다.

http://www.jennifersoft.com
http://sales.jennifersoft.com

사용자가 http://www.jennifersoft.com 도메인 이름으로 서비스하는 웹 애플리케이션을 처음 사용하면 새로운 wmonid 쿠키 값이 배정된다. 그런데 이 사용자가 http://sales.jennifersoft.com 도메인 이름으로 서비스하는 웹 애플리케이션에 접근해도, 앞의 웹 애플리케이션에서 배정된 wmonid 쿠키 값을 읽을 수 없기 때문에 새로운 wmonid 쿠키 값이 배정된다. 따라서 이 사용자는 동일한 사용자 임에도 불구하고 이중으로 계산된다.

상황에 따라서 앞에서 설명한 방식대로 물리적으로 동일한 사용자라고 하더라도 도메인 이름별로 구분해서 계산하는 것이 적절할 수 있다. 그러나 이를 동일한 사용자로 계산하려면 제니퍼 에이전트의 default_cookie_domain 옵션을 사용한다.

default_cookie_domain = .jennifersoft.com

default_cookie_domain 옵션 값은 반드시 [.]로 시작해야 한다. 만약 이 옵션을 설정하면 도메인 이름이 아닌 IP 주소로 접속하는 사용자는 동시단말 사용자 수와 방문자 수에 영향을 미치지 못한다.

앞에서 설명한 내용은 제니퍼 에이전트 별 방문자 수나 동시단말 사용자 수와 관련한 내용이 아니고, 모든 제니퍼 에이전트에 대한 전체 방문자 수와 전체 동시단말 사용자 수와 관련한 것이다.

대기 시간

대기 시간은 wmonid 쿠키 값이 동일한 트랜잭션들의 평균 호출 간격을 의미한다.

대기 시간은 제니퍼 에이전트가 수집하는 일반 성능 데이터로 실시간 30초 평균 값을 런타임 라인 차트를 통해서 확인할 수 있다.

최근 대기 시간

또한 대기 시간에 대한 5분 평균 값은 PERF_X_01~31 테이블의 THINKTIME 칼럼에 저장되고, 특정 날짜의 대기 시간 변화 추이는 라인 차트를 통해서 확인할 수 있다.

금일 대기 시간

액티브 사용자 수

이론적으로는 HTML 프레임이나 AJAX 등의 개발 기법과 탭 브라우징 등의 웹 브라우저 인터페이스의 변화로 2개 이상의 액티브 서비스가 동일한 사용자와 연결될 수도 있다.

즉, 액티브 서비스 중에 wmonid 쿠키 값이 동일한 트랜잭션이 있을 수 있다. 액티브 사용자 수는 액티브 서비스 중에서 wmonid 쿠키 값이 동일한 트랜잭션들을 하나로 간주하여 계산한 것이다.

액티브 사용자 수에 대한 5분 평균 값은 PERF_X_01~31 테이블의 ACTIVE_USER 칼럼에 저장된다.

액티브 사용자 수는 차트로 제공하지 않는다.

방문자 수

방문자 수는 wmonid 쿠키 값의 존재 여부와 시간 구간을 기준으로 수집한다. 시간 구간은 날짜와 시간으로 구분된다. 날짜를 기준으로 수집한 것은 일일 방문자 수이고 시간을 기준으로 수집한 것은 시간당 방문자 수이다.

예를 들어, 10월 10일 01시 25분에 wmonid 쿠키가 없는 트랜잭션이 들어오면 일일 방문자 수가 1이 증가하고, 01시에 해당하는 시간당 방문자 수도 1이 증가한다.

그리고 10월 10일 02시 03분에 wmonid 쿠키가 있는 트랜잭션이 들오여면 일일 방문자 수는 증가하지 않지만, 02시에 해당하는 시간당 방문자 수는 1이 증가한다. 즉, 시간이 변경되면 wmonid 쿠키의 존재 여부와 상관없이 시간당 방문자 수가 증가한다.

그런데 10월 09일에 이미 방문한 사용자에 의해서 10월 10일 01시 01분에 트랜잭션이 들어오면 이 트랜잭션에는 wmonid 쿠키가 존재한다. 그럼에도 10월 10일 일일 방문자 수는 1이 증가한다. 즉, 날짜가 변경되면 wmonid 쿠키의 존재 여부와 상관없이 일일 방문자 수가 증가한다.

방문자 수는 일반 성능 데이터로 5분 동안 증가한 시간당 방문자 수는 PERF_X_01~31 테이블의 VISIT_HOUR 칼럼에 저장되고, 5분 동안 증가한 일일 방문자 수는 PERF_X_01~31 테이블의 VISIT_DAY 칼럼에 저장된다. 특정 날짜의 방문자 수 변화 추이는 막대 차트를 통해서 확인할 수 있다.

금일 시간당 방문자 수

시간을 고려해서 방문자 수를 계산할 때 주의할 것은 제니퍼 서버의 재시작이다. 제니퍼 서버는 방문자 수 계산을 위해서 모든 wmonid 쿠키 값을 자바 힙 메모리에 상주시킨다. 그런데 제니퍼 서버를 재시작하면 자바 힙 메모리에 상주되어 있던 wmonid 쿠키 값이 모두 사라지기 때문에 방문자 수가 정확하지 않을 수 있다.

이 문제를 해결하기 위해서 제니퍼 서버를 재시작할 때, 제니퍼 서버 재시작 전 까지 수집한 방문자 수를 제니퍼 서버를 재시작한 후에 새로 수집한 방문자 수에 합산할지 여부를 결정할 수 있다. 제니퍼 에이전트의 enable_visit_user_added_while_reloading 옵션을 true로 설정하면 합산을 하고, false로 설정하면 합산하지 않는다.

enable_visit_user_added_while_reloading = true

일반적으로 쇼핑몰처럼 매번 사용자가 바뀌는 시스템은 true로 설정하고, 회사 내부 시스템처럼 사용자가 고정된 경우에는 false로 설정하는 것이 일반적인다. 기본값은 false이다.

동시단말 사용자 수

동시단말 사용자 수에 대한 이해

동시사용자 = 요청간격 * 초당처리건수

다음 그림은 한 사용자가 웹 애플리케이션에 접속하여 최초로 클릭을 한 후, 그 다음 페이지로 이동하면서 클릭을 반복하고 이후 최종적으로 웹 애플리케이션을 떠나는 모습을 간략하게 형상화 한 것이다. 다른 사용자들 또한 서로 다른 시간에 해당 웹 애플리케이션에 방문하여 이러한 모습으로 서비스를 사용할 것이다.

동시단말 사용자 수에 대한 이해

이때 클릭과 클릭 사이의 시간을 대기 시간으로 정의하고, 최초로 방문한 시간부터 마지막 클릭 까지의 시간을 방문 시간으로 정의한다. 이 상황에서 임의로 특정 시간대를 선으로 그어 해당 시각에서의 접속자 혹은 동시단말 사용자 수를 확인해 보면 6명(해당 그림에서)이 사용하고 있음을 확인할 수 있다. 즉, 동시단말 사용자 수란 특정 시점에 웹 애플리케이션에 접속하여 사용하고 있는 모든 사용자의 수를 의미한다.

동시단말 사용자 수는 제니퍼 에이전트가 수집하는 일반 성능 데이터로 실시간 30초 평균값을 런타임 라인 차트를 통해서 확인할 수 있다.

최근 동시단말 사용자 수

또한 동시단말 사용자 수에 대한 5분 평균 값은 PERF_X_01~31 테이블의 CONCURRENT_USER 칼럼에 저장되고, 특정 날짜의 동시단말 사용자 수 변화 추이는 라인 차트를 통해서 확인할 수 있다.

금일 동시단말 사용자 수

동시단말 사용자 수의 측정

제니퍼가 동시단말 사용자 수를 측정하는데 사용하는 알고리즘은 성능 이론에 기반을 두고 있으며, 현재 컴퓨터 앞에 앉아서 웹 애플리케이션을 사용하고 있는 사람의 수를 보다 정확하게 측정하기 위한 획기적인 방법이다. 과거 클라이언트/서버 방식의 시스템에서는 단순히 TCP/IP 연결 개수를 동시단말 사용자 수로 간주할 수 있었지만, HTTP 프로토콜은 사용자 컴퓨터와 서버 사이의 연결을 지속시키지 않고 사용자의 요청을 직접적으로 처리할 때만 연결을 맺는 방식이기 때문에 TCP/IP 연결 개수를 동시단말 사용자 수로 간주할 수는 없다. 그래서 제니퍼는 성능 이론을 토대로 하는 다음의 동시단말 사용자 수 측정 알고리즘으로 동시단말 사용자 수를 측정한다.

동시단말 사용자 수 측정 알고리즘

웹 애플리케이션의 부하량(Throughput)이 높을수록 정확한 수치에 수렴해 간다는 것이 수학적으로 증명되었고, 수십회의 웹 성능 테스트를 통한 시뮬레이션과 실제 운영 시스템에 대한 모니터링 결과 이 알고리즘으로 측정한 동시단말 사용자 수 수치의 정확성은 검증되었다.

예를 들어, 큰 홀에 모인 500 명의 사용자가 동일한 시스템에 접속하여 사용하면 제니퍼가 측정한 시스템의 동시단말 사용자 수나 웹 애플리케이션 서버의 javax.servlet.http.HttpSession 객체의 개수는 모두 500이 된다. 그런데 500 명이 점식 식사를 위해서 모두 자리를 일어나 큰 홀을 떠나면 제니퍼가 측정한 동시단말 사용자 수는 곧바로 0이 되지만 웹 애플리케이션 서버의 javax.servlet.http.HttpSession 객체의 개수는 세션 타임아웃 기간 동안은 계속 500이 된다.

간혹 동시단말 사용자 수가 급격하게 커지는 현상이 나타날 때가 있다. 이러한 현상은 TPS와 응답 시간, 대기 시간을 이용한 계산에 의한 문제로 기술적으로 발생할 수 있다. 이러한 경우에는 해당 수치를 무시하고 정상 상황에서의 값들을 기준으로 분석을 해야 한다.

동시단말 사용자 수의 활용

동시단말 사용자 수는 성능적으로 매우 중요하지만, 기술적인 문제로 장애가 발생해서 동시단말 사용자 수가 증가한건지 동시단말 사용자 수가 증가해서 장애가 발생했는지에 대한 인과 관계를 파악하기 어려울 수 있다. 따라서 동시단말 사용자 수를 직접적인 장애 원인 분석 수단으로 활용하는 것은 권장하지 않는다.

그러나 웹 애플리케이션의 성능 테스트 단계에서 동시단말 사용자 수는 성능 테스트 환경과 운영 환경의 성능 지표간의 연관도를 파악하는데 중요한 역할을 한다.

즉, 가상 사용자를 지정하고 업무별 워크로드를 설계하여 부하 테스트를 하게 되는데, 이때 가상 사용자는 제니퍼의 동시 단말 사용자 수와 직접적으로 연관된다. 따라서 이것을 기준으로 부하 테스트의 워크로드가 실제 운영 환경의 워크로드과 유사한지 등을 파악할 수 있다.

전체 성능 데이터와 제니퍼 에이전트 그룹

하나의 제니퍼 서버가 모니터링하는 제니퍼 에이전트의 숫자가 많은 경우에 전체 방문자 수 혹은 전체 동시단말 사용자 수를 계산하는 방법을 설명한다.

예를 들어, 09시에서 10시 까지의 W11 제니퍼 에이전트의 시간당 방문자 수는 120명이고 , W12 제니퍼 에이전트의 방문자 수는 140명이고, W13 제니퍼 에이전트의 방문자 수는 70명이라고 가정하자.

전체 방문자 수를 계산하는 가장 손쉬운 방법은 모든 제니퍼 에이전트의 방문자 수를 합하는 것이다. 따라서 이 경우에 전체 방문자 수는 330명이 된다.

그런데 동일한 사용자가 09시에서 10시 까지 W11, W12, W13 제니퍼 에이전트를 모두 방문했다면 전체 방문자 수가 중복 계산되어 실제 수치보다 클 수 있다. 이 문제를 해결하기 위해서 제니퍼 서버는 wmonid 쿠키 값을 활용해서 동일 사용자가 중복 계산되는 것을 방지한다.

그런데 경우에 따라서는 전체 제니퍼 에이전트가 아닌 특정 제니퍼 에이전트 그룹에 대한 전체 방문자 수나 전체 동시단말 사용자 수를 측정해야할 필요가 있다.

예를 들어, W13 제니퍼 에이전트를 제외한 W11 제니퍼 에이전트와 W12 제니퍼 에이전트에 대한 전체 방문자 수를 계산하려면 제니퍼 서버의 agent_group 옵션을 사용한다.

agent_group = 그룹아이디:에이전트목록

제니퍼 에이전트 그룹 아이디는 반드시 ‘@’ 로 시작하고 2자리의 숫자로 끝나야 한다. 따라서 제니퍼 에이전트 그룹 아이디로는 @01에서 @99 까지 사용할 수 있다.

그리고 제니퍼 에이전트 그룹에 속하는 제니퍼 에이전트 목록은 제니퍼 에이전트 아이디를 [,]를 구분자로 구분해서 설정한다. 따라서 앞의 예제는 다음과 같이 설정한다.

agent_group = @01:W11,W12

2개 이상의 제니퍼 에이전트 그룹은 [;]을 구분자로 구분한다.

agent_group = @01:W11,W12; @02:W13,W14

제니퍼 에이전트 그룹 아이디는 제니퍼 에이전트 아이디와 동일한 역할을 한다. 따라서 제니퍼 에이전트 그룹 아이디별로 PERF_X_01~31 테이블에 모든 성능 데이터가 저장된다.

동일한 제니퍼 에이전트를 2개 이상의 제니퍼 에이전트 그룹에 설정할 수는 없다.

Batch JOB Monitoring

Batch JOB의 특징

Batch job 이란 실행되여 지정한 로직을 수행한후 종료되는 프로그램이다. Batch JOB 프로그램은 다음과 같은 특징이있다.

Batch Job 모니터링은 이러한 특징을 갖는 프로그램의 성능을 모니터링 하는 것을 말한다

제니퍼의 Batch JOB 모니터링 기본 개념

배치잡은 짧은 시간동안 실행되고 정지 된다. 따라서 배치잡 하나를 온라인에서 서비스 형태로 모니터링한다.

제니퍼의 Batch JOB 모니터링 기본 개념

에이전트를 분리한다.

제니퍼 관점에서는 서비스는 에이전트 아이디를 가진 프로세스에 의해 수행된다. 따라서 별도의 가상의 마스터 에이전트를 두고 각각의 배치잡에서 직접 정보를 수집하기 위한 서브에이전트를 둔다.

UDP 중심 정보 수집

배치잡은 ?은 시간에 종료된다 따라서 TCP 세션을 유지하는 것이 큰잇점이 없다. 따라서 대부분의 정보를 UDP통해서 수집한다.

액티브스택을 위해 TCP세션을 사용한다.

주기적인 통계정보는 UDP통해서 수집하지만 현재 진행중인 배치잡의 액티브 스택이나 액티브 프로파일을 조회하기 위해선 여전히 TCP세션이 필요하다.

Batch JOB 모니터링을 위한 제니퍼 아키텍처

Batch JOB 모니터링을 위한 제니퍼 아키텍쳐

  1. Runtime Data(Transaction Start/End)와 프로파일 데이터가 전송된다 제니퍼서버입장에서는 어느 SubAgent인지 심지어 이데이터가 일반적인 제니퍼 에이전트에서 온것인지 구분하지 않는다.

  2. SubAgent가 MasterAgent로 연결하는 TCP세션이다. 이곳으로는 MasterAgent로 부터 보내진 요청에 대한 응답만을 전송한다. 또한 이 세션이 종료되면 자동으로 다시 연결한다. 이곳에서는 액티브 서비스리스트나 각 쓰레드의 상세 액티브스택/액티브 프로파일 정보등이 전달된다.

  3. 매초마다 보내는 Summary Data가 MasterAgent로 전송된다. 그리고 SubAgent에서 수집되는 텍스트 데이터(SQL, Application Name, Method Name) 등이 이곳으로 전송된다. 그리고 SubAgent는 애플리케이션 및 SQl수행 통계를 주기적으로 혹은 프로세스가 종료될때 (3)을 통해 전송한다.

  4. 제니퍼 서버는 MasterAgent를 일반적인 제니퍼 Agent로 간주하고 통신한다. 특히 SubAgent가 (3)을 통해 전달한 통계 정보를 모아 두었다가 10분에 한번씩 (4)를 통해 제니퍼 서버로 전송한다.

  5. MasterAgent는 (3)을 통해 SubAgent가 보내주는 SummaryData들 하나로 통합하여 매 초마다 제니퍼서버로 전송한다. MasterAgent에서는 직접적으로 서비스가 수행되지 않기 때문에 서비스 시작/종료나 프로파일 정보는 발생하지 않는다.

중요 특징은 데이터 수집을 위해 UDP를 사용하고 제어를 위해 TCP를 사용한다. TCP Listening은 마스터에이전트가 하고 서브에이전트는 실행과 동시에 하나의 TCP세션을 마스터 에이전트에 연결한다.

SubAgent설치

SubAgent를 설치할때는 일반적인 제니퍼 에이전트를 설치하는 방법과 동일하다. 다만 현재의 에이전트 실행모드가 SubAgent라는 것과 마스터 에이전트 그리고 제니퍼 서버의 네트웍 정보를 설정해야 한다.

-Djennifer.subagent=true
master_host_name = 127.0.0.1
master_udp_listen_port = 6705

따라서 SubAgent와 MasterAgent를 동일 머신에 설치하는 경우에는 설정파일은 공유하는것이 좋다.

.MasterAgent설치

마스터 에이전트는 단순히 실행만 하면된다. 제니퍼 에이전트디렉토리에는 “masteragent.sh/bat” 파일이 포함되어있다. 이 파일을 실행한다.

java -Xbootclasspath/p:./lwst.boot.jar \
       -cp ./jennifer.jar \
       -Djava.library.path=. \
       -Djennifer.config=w11.conf \
       com.javaservice.jennifer.agent.master.MasterAgent

마스터 에이전트는 서브에이전트로 부터 UDP데이터를 수신한다. 따라서 리스닝 포트를 지정해야 한다. jennifer.conf 설정에 다음 설정을 추가하다 만약 지정하지 않으면 6705가 기본값이다.

master_udp_listen_port = 6705

제니퍼 에이전트 디렉토리로 이동하여 다음 파일을 실행한다.

masteragent.bat

프로파일 설정

배치잡은 많은 수의 SQL이 실행될 가능성이 있다 만약 프로파일 데이터가 너무 많다면 중요도가 떨어지는 항목부터 제외해야 한다. 이것을 위해 몇가지 옵션들이 추가되었다.

profile_ignore_connection=false
profile_ignore_fetch=false
profile_sql_time=0

위 설정 예는 기본값이다

마스터와 서브 에이전트 사이의 텍스트 케쉬제어

서브에이전트는 UDP를 통해서 전송된다. 이때 이미 전송된 목록을 기록해 두는 케쉬가 있는데 크기를 수정할 수 있다.

master_max_num_of_text = 1000
master_max_num_of_sql = 5000

APP, TX, ERR의 케쉬는 master_max_num_of_text를 따르고 SQL 수는 master_max_num_of_sql에서 설정된다.

서브 에이전트는 택스트 자체는 보관하지 않고 보냈다는 기록만을 보관하기 때문에 이값을 좀더 크게 설정해도 된다. 이값이 충분히 크면 텍스트는 서브에서 마스터로 단 한번만 전송되게 된다. 그러나 서브에이전트가 재기동되면 처음부터 다시 전송한다.

유사하게 마스터 에이전트는 서브에이전트로 부터 받은 텍스트를 보관하는 별도의 케쉬를 가지고 있다. 이 값또한 master_max_num_of_text, master_max_num_of_sql에 의해 크기가 정해진다.

닷넷 배치 프로세스 모니터링

이 장에서는 닷넷 버전의 제니퍼 에이전트를 이용하여 배치(Batch) 작업을 모니터링하는 방법을 설명한다.

제니퍼에서 구현되는 배치 모니터링의 개념 및 자바에서의 설치방법은 ” Batch JOB Monitoring” 문서를 참고한다.

MasterAgent 설치 및 실행

conf 파일 설정

” [에이전트 설치 폴더]\conf\app_pool.conf” 파일을 복사해서 “batchjob_master.conf” 파일을 생성한다. 제니퍼 서버와 연결되어야하므로, batchjob_master.conf 파일을 메모장에서 열고, 제니퍼 서버 주소를 설정한다.

udp_server_host = [제니퍼 서버 주소]

마스터 에이전트 실행

마스터 에이전트 실행파일은 JENNIFER와 함께 설치되므로 별도의 설치작업은 필요없고 단순히 아래의 경로에 제공되는 모듈을 실행하면 된다.

.NET 1.1: [에이전트 설치 폴더]\bin\MasterAgent.Clr10.exe
.NET 2.0 이상: [에이전트 설치 폴더]\bin\MasterAgent.exe

SubAgent 설치 및 실행

서브 에이전트는 모니터링 해야 할 대상을 의미하는데, 제니퍼 에이전트가 활성화 되는 배치 프로세스(exe)가 이에 해당한다.

conf 파일 설정

서브 에이전트가 종속될 마스터 에이전트의 conf 파일을 복사해서 새롭게 conf 파일을 생성하고 서브 에이전트 임을 명시하기 위해 다음의 설정을 추가한다.

[예: youragent.conf]
SUB_AGENT = true

배치 프로세스에 conf 파일 연결

모니터링하려는 배치 프로세스의 실행 파일 경로가 다음과 같다고 가정할 때,

C:\BatchJobs\DailyWorker.exe

해당 프로세스 명에 ” .config” 파일을 연결하여 conf 폴더에 새롭게 파일을 생성한다.

[에이전트 설치 폴더]\conf\DailyWorker.exe.config

파일의 내용은 아래와 같이 이전에 서브 에이전트 용으로 만들어 둔 conf (예:youragent.conf) 를 지정한다.

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
   <appSettings>
      <add key="Jennifer.FileName" value="youragent.conf" />
   </appSettings>
</configuration>

사용자 정의 메서드 프로파일링 설정

일반적으로 배치 프로세스에서는 사용자가 정의한 메서드를 트랜잭션 단위로 여기게 된다. 따라서, ” 닷넷 메서드 프로파일링 “에서 설명한 방법에 따라 ” [txserver]” 절을 별도로 구성해야 한다.

또한, 배치 프로세스의 경우 반드시 ” [batchjob]” 절을 정의하고 해당 응용 프로그램의 Main 함수를 정의해 줘야 한다.

예를 들어 사용자 코드가 다음과 같이 정의된 경우,

namespace BatchJob1
{
   class Program
   {
      static void Main(string[] args)
   {
   }
      void DoBatchJob()
   {
   }
  }
}

만약, DoBatchJob 이 실제 배치 작업을 처리하는 메서드이고 txserver 로 모니터링해야 할 대상이라면 profiler.ini 파일에는 다음과 같이 설정해 주어야 한다.

[batchjob.프로세스명]
BatchJob1.Program.Main=1

[txserver.프로세스명]
BatchJob1.Program.DoBatchJob=1

제니퍼 에이전트 환경변수 설정

배치 프로세스가 프로파일링되기 위해서는 다음의 환경 변수를 프로세스 실행 전에 설정한다.

SET COR_ENABLE_PROFILING=1
SET COR_PROFILER={FF8C2B6C-DBB5-4AED-9876-2CED6FFAF4C9}

환경 변수는 여러가지 방법으로 설정이 가능한데, .bat 파일 또는 NT 서비스의 경우에는 레지스트리를 이용하는 방법은 ” 환경 변수 설정 “을 참고한다.

만약, 그 2가지 방법으로 설정할 수 없는 경우라면 전역적으로 환경 변수를 설정하는 것도 가능하다. 시스템 환경 변수로 등록되는 경우, 해당 운영체제에서 실행되는 모든 닷넷 프로세스는 제니퍼 에이전트의 프로파일링 작업이 이뤄지기 때문에 원치 않는 성능 저하를 야기할 수 있다. 이런 부작용을 해결하기 위해서 제니퍼 닷넷은 “JENNIFER_PROFILE” 이라는 별도의 환경 변수 옵션을 인식한다. 따라서, 사용자의 배치 프로세스 명이 “DailyWorker.exe” 인 경우 다음과 같이 환경 변수를 등록해 줄 수 있다.

환경 변수 이름: JENNIFER_PROFILE
값: dailyworker.exe

프로세스 명은 반드시 소문자로 지정해야 한다.

만약, 배치 프로세스가 여러 개인 경우 세미콜론(;)을 구분자로 해서 다음과 같이 지정하는것이 가능하다.

환경 변수 이름: JENNIFER_PROFILE
값: dailyworker.exe;weeklyworker.exe;monthlyworker.exe

설정을 마치고, 해당 배치 프로세스를 실행하면 정상적으로 모니터링이 이뤄진다.

에이전트 모니터링 해제 / 제거

제니퍼 에이전트가 설치된 상태에서, 배치 프로세스에 대한 모니터링만을 해제하고 싶다면 환경 변수에서 “COR_ENABLE_PROFILING” 값을 “0” 으로 변경하면 된다. (또는 “JENNIFER_PROFILE” 로 설정된 경우라면, 프로세스 명을 빼거나 JENNIFER_PROFILE 환경 변수 자체를 지우면 된다.)

만약, 제니퍼 에이전트 까지 모두 제거하고 싶다면 현재 모니터링 중인 배치 프로세스를 모두 종료하고 “[에이전트 설치 폴더]/uninstall_Jennifer.bat” 을 관리자 권한으로 실행한 후, 설치 폴더를 수동으로 삭제해 준다.

업무단위 모니터링

업무단위 모니터링은 JENNIFER® 4.5에서 강화된 기능이다 사용자는 업무단위(그룹)로 성능을 모니터링 할수 있다.

업무단위 모니터링

업무단위 모니터링의 최근 5분동안의 성능을 표현한다. 업무단위 성능에는 최종사용자 응답시간, 평균 서비스 응답시간, 외부트랜잭션 처리시간 SQL수행시간 및 패치시간, 초당 처리건수등이 포함된다.

또한 업무단위 모니터링 화면 세부 업무그룹 이름을 클릭하면 각 서비스 처리별 성능을 X-View를 통해 확인할 수 있다.

업무단위 모니터링 화면 세부 업무그룹

업무 단위 설정

업무 단위 모니터링을 [Properties | Business Group]에서 설정할 수 있다. 업무ID를 클릭하여 내용을 수정하거나 [Add] 버튼을 클릭하여 새로운 그룹을 추가할 수 있다.

업무 단위 설정

각 업무그룹은 유일한 “ID” 를 사용해야 한다. 새 업무그룹에는 반드시 ID와 Name을 지정하고 SLA기준값을 설정한다. 해당 그룹의 서비스중에 SLA기준값을 초과하는 서비스가 발생하면 sla_fail로 카운팅된다. 수정된 그룹은 Status를 Active로 설정해야 적용된다.

애플리케이션에는 서비스명칭을 Prefix혹은 Postfix등을 이용하여 설정할 수 있다. 예를들 어 *(cmd=a07)라고 설정하면 (cmd=a07)로 끝나는 서비스를 그룹으로 지정하는 것이다.

마지막으로 수정된 업무그룹이 적용되려면 [APPLY] 버튼을 클릭해야 한다.