IBM 
-Xdump:tool:events=throw,filter=java/lang/OutOfMemoryError,exec="kill -9 %pid"

JRockit
-XXexitOnOutOfMemory

SUNVM
UNIX: -XX:OnOutOfMemoryError="kill -9 %p"
Wind: -XX:OnOutOfMemoryError="taskkill /F /PID %p"

Posted by sjokim
,
문제의 정의
문제는 현 상태와 목표 상태의 차이를 말한다. 문제는 현 상태에 대한 측정과 목표 상태에 대한 결정에 의해 정의된다. 일반적으로  성능문제는 목표를 정의하는 것이 어렵다. 
성능문제 해결 활동을 시작할때는 문제의 정의 부터 심각하게 해야 한다.

성능 목표의 결정이 어려운 이유는
현 상태파악이 어려움: ex 성능 테스트를 거쳐야 개발 시스템의 처리량 파악이 가능
목표 수립이 어려움: ex Legacy 시스템에 대한 성능 분석과 추가된 FACT들을 종합해야만 목표수립이 가능

성능문제 해결이란?
사회현상에 대한 문제 해결은 원인을 찾는 것보다 원인을 제거하는 것 까지가 문제 해결이다 하지만 성능문제 해결에서는 문제의 원인을 찾아내는 것까를 해결로 보며 그것을 시스템에 반영하는 것은 "조치" 라고 한다.

Posted by sjokim
,
엔터프라이즈 애플리케이션의 복잡도는 갈 수록 증가하고 있다. 그만큰 성능을 보장하기 위한 노력들도 더해지고 있다. 성능을 보장하기 위해서는 가능한 빈번히 성능테스팅을 수행해야 하는데, 성능테스팅을 위한 비용또한 증가하고 있다. 큰 이유중 하나가 애플리케이션 아키텍처가 복잡해지기 때문에 정상적인 성능테스팅을 위한 준비작업들이 어려워 지고 있기 때문이다.
따라서 테스팅이 쉽게 될 수 있도록 애플리케이션 구조를 설계하기 위한 고려사항들을 제시하고자 한다.

Test Gateway를 만들라
서버의 애플리케이션이 단순한 HTTP프로토콜에 의해 호출되는 경우에는 성능테스팅이 쉽다. 하지만 XINTERNET 클라이언트라든지 애플릿혹은 ActiveX클라이언트에 의해 호출되는 애플리케이션을 테스팅하는 것은 가장 효과적인 테스팅 툴을 사용하더라도 많은 시간을 요구한다.
이런 경우 HTTP프로토콜을 사용하는 별도 GateWay를 둠으로써 쉽게 테스팅을 수행할 수 있게된다. 즉 애플리케이션 서버에 쉽게 실제 비즈니스로직을 호출해 볼수 있는 Gateway 역할의 Servlet이나 JSP를 만들어 외부에서 그것을 호출함으로써 쉽게 서버의 애플리케이션 성능을 검증해 볼 수 있을 것이다.

설정에 의한 Bypass 방법을 만들라
애플리케이션의 로직에는 오로지 비즈니스를 위한 로직만 포함되는 것이 아니다. 침임탐지 로직, 권한관리 로직등 비즈니스와 직접 관련이 없는 로직들도 포함되어있다. 이러한 부분은 시스템의 안정성을 위해 필요하지만 그만큼 테스팅을 어렵게 한다. 따라서 테스팅을 위해 필요한 경우 이러한 로직들을 Bypass할 수 있도록 구현해 둘 필요가 있다.

외부서비스와 Junction부에 더미 Stub을 만들라
트랜잭션이 단순히 내부 데이타나 로직만을 기반으로 수행된다면 쉽지만 외부연결(Junction)이 존재하면 외부 시스템까지 테스팅 가능한 상태가 되어야 한다. 그래서 이부분의 연결을 더비 스텁으로 끊어 내면 손쉽게 테스팅을 할 수 있다.
일반적으로 성능을 테스팅할때 외부 시스템때문에 애플리케이션에 충분한 부하를 발생시키지 못한다.이런 문제는 더비 스텁을 통해 해결이 가능하다.

추가이슈
애플리케이션 아키텍처 설계만으로 해결되지 않는 문제들이 있다. 개발 중의 애플리케이션은 계속변경된다. 그렇게 매주마다 추가되고 변경되는 애플리케이션의 성능을 테스팅하기 위해서는 테스팅 파라미터와 이것에 대한 부하를 효과적으로 발생시키기 위한 고려가 필요하다.
  • 어떻게 변경되는 트랜잭션에 대한 테스트 파라미터를 확보할 것인가?
  • 어떻게 부하를 발생시킬 것인가?

'성능과 장애' 카테고리의 다른 글

OOM을 위한 처리옵션  (0) 2012.03.21
<Joe> 성능문제 해결의 일반론  (0) 2009.10.30
Application Monitorability을 위한 설계 고려사항  (0) 2009.10.27
문제 해결을 위한 TOOLS  (0) 2009.10.26
OutOfMemoryError 해결  (0) 2009.10.26
Posted by sjokim
,
성능을 고려한 소프트웨어 아키텍쳐 설계에서 Monitorability는 중요한 품질 요소중에 하나이다. 다음은  Monitable한 프로그램 설계 시 고려사항이다.

명확한  서비스 명을 쉽게 추적할 수 있도록 설계 한다.
모니터링에서 서비스 명을 가장 중요한 기본 항목이다. 모든 서비스는 클라이언트 요청을 받아 결과를 리턴한다. 이때 이 처리를 트랜잭션이라 한다. 서비스는 요청 파라미터와 로직에 따라 다른 결과을 리턴할 수 있는데 심지어 전혀 다른 로직을 수행할수도 있다. 예를 들어 계좌 이체를 하는데 동일 은행 이체가 될 수도 있고 타행이체가 될 수도있다 이것은 전적으로 타겟 계좌의 은행과 계좌번호에 의해 분기된다. 둘사이의 로직은 전혀 다를 것이며 이 둘의 트랜잭션이 동일한 서비스 명으로 모니터링 된다면 성능 분석이 원할이 될 수 없다.
웹 애플리케이션에서 서비스명을 URL이 될 수 있지만 이것은 전적으로 프레임웍에 따라 달라진다. 따라서 프로그램 구조를 설계할때 정확한 서비스 명이 어떤것이고 어떻게 추출되어야 하는지를 명확히 해야 한다.

트랜잭션 시작부분을 단순화 한다.
서비스는 일반적으로 네트웍으로 부터 요청을 받아 리턴한다. 그렇다고 모든 서비스의 시작이 네트웍 소켓 모듈에서 시작한다고 정의할 수 없다. 그중에는 의미없는 요청이 있을 수도 있으며, 실제 구체적인 서비스 구분이 되지 않았기 때문이다. 웹 애플리케이션에서 서비스 시간은 JavaEE스팩에 의해 이미 결정되어있다. 하지만 통신 중계데몬이나 중계 프로세스의 시작은 불분명한 경우가 더러있는데 아키텍처 설계단계에서 그 시작점(클래스/메소드)을 명확히 정의해야 한다.

트랜잭션에서 의미있는 스텝과 외부 연결부를 단순화 한다.
스텝이란 트랜잭션의 로직 흐름에서 의미있는 지점을 말한다. 특히 외부 연결부가 별로 없는 트랜잭션에서는 적절한 위치를 고려해 두어야 한다. 하지만 외부 트랜잭션 호출이나 DB Access같은 외부 서비스을 호출하는 연결부(Junction)이 많은 경우에는 별도 스텝을 고려할 필요가 없다, Junction이 트랜잭션 스텝으로서의 역할을 같이 수행할 것이다.
스텝이나 연결부를 단순화 하기 위해서는  다음 패턴을 고려할 수 있다.
  • Facade 패턴: 복잡한 서브 클래스들을 묶어 명확한 진입점을 정의한다. 모니터링시 Facade클래스를 프로파일링함으로서 해당 구간의 로직의 성능을 판별한다.
  • Proxy 패턴 : 특히 외부 시스템과 연결된(JUNCTION) 부분은 반드시 단순화되고 명확한 Proxy 클래스를 정의하고 이것만 모니터링하면 외부 시스템의 성능을 판별할 수있도록 한다.
연결부의 이름 정보를 쉽게 추적할 수 있도록 설계한다.
턱시도 클라이언트 모듈에서 턱시도 서비스를 호출하는 경우 서비스명이 프로파일정보에 나타나야 한다. 이렇듯 모든 연결부(JUNCION)에서는 외부 서비스 명을 쉽고 정확하게 추출할 수 있도록 설계해야 한다. 특히 해당 연결부의 응답시간과 이름이 같이 모니터링 될 수 있어야 한다.
예를 들어 비동기 통신을 하는데 그데이터 내부에 의미있는 외부 서비스 명이 숨어 있다면 효과적인 모니터링이 어렵다.

내부 자원에 대한 모니터링을 고려한다.
모니터링이 필요한 프로세스 내부 로직컬 자원을 정리하고 그것으로 부터 정보를 추출할 수 있는 액세드 모듈을 정의해 둔다. 그래야만 모니터링 툴에서 그것을 다른 정보와 통합모니터링할 수 있다.

프로파일링이 가능하도록 설계한다.
자바나 .NET은 프로파일링이 가능하도록 프로그램 언어 레벨에서 지원한다. 하지만 C/C++등 기타 언어로 프로그램 되어있는 경우에는 기본 상태에서 프로파일링이 불가능하다. 이런 경우에 중요 스텝과 연결부를 정리하고 그곳에서 프로파일정보를 수집할수 있는 방안을 마련해 둔다면 보다 효과적으로 성능 모니터링이 가능하게된다.

크리티컬 이벤트를 모니터링할 수 있도록 설계한다.
일반적인 프로파일링이나 모니터링 툴에서는 비즈니스를 감안한 문제를 모니터링 하기는 어렵다. 하지만 중요 비즈니스 로직적 오류시 그것을 운영담당자가 인지하는 것은 필요하며 이런경우 그 이벤트를 추적할 수 있는 메커니즘을 설계해 둘 필요가 잇다.
간단하게  이벤트라는 클래스를 두고 프로그램 로직에서 중요 크리티컬한 로직 에러가 발생하면 그 내용과 시간을 셋팅하고, 툴은 그 값의 변화를 모니터링 하다고 경보하도록 구현할 수 있을 것이다.

Monitorability는 얼마나 쉽게 성능과 오류를 모니터링 할 수 있도록 설계했느냐 이다. 모니터링이 쉽다는 것은 그만큼 전체 성능의 정확한 상태나 프로그램 오류를 정확히 파악할 수 있고 개선하기 쉬워진다. 예를 들어 트랜잭션 전체에서 Exception Handling을 한곳에서 하도록 설계한다면  이곳만 관찰하면 트랜잭션의 성공과 실패 혹은 기타 문제를 정확히 알 수 있다 

모니터링은 데이터를 추룰하는것만 아니고 이것을 비쥬얼화 하는 것까지를 포함하기 때문에 솔류션 의존적인 면이 있다. 즉 모니터링을 위해서는 단순한 로깅 이상의 프로그램 기술이 필요하기 때문이다. 그래서 Monitability를 고려할때는 모니터링 솔루션의 기능을 고려해야 한다. 그리고 그것을 최대한 활용하도록 설계해야 한다. 하지만 특정 모니터링 툴이 그 시스템에서 제거되더라도 아무런 문제가 없도록 설계되어야 한다.


 


Posted by sjokim
,

1.1 가설기반 문제해결

성능 문제를 해결하기 위해서는 현상을 수집하고 그것을 기반으로 가설을 수립하며 이것을 검증하는 과정을 반복함으로써 해결될  있다.



해결해야  문제가 발생하면 먼저 현상/Fact 수집한다. 각종 현상들 로그 기록들 혹은 테스트결과들은 모두 팩트로 정리될  있다. 팩트는 가능한 풍부하고 정확해야 문제 해결을 빠르게  있다.

 다음에는 수집된 팩트를 기반으로 가설을 수립한다. 의미 있는 가설 수립을 위해서는 튜너의경험과 지식이 요구된다. 가설을 최종적으로 해결해야  문제의 원인을 해결하거나 해결에 도움이 되어야 한다. 검증되어도 문제를 풀어가는데 도움이 않되는 가설은 검증할 필요가 없다.

주의)가설은 팩트가 아니다 즉 검증되기 전까지는 가설일 뿐이다. 만약 관리자나 고객에게 가설이 팩트 처럼 전달된다면 튜닝은 엉뚱한 방향으로 진행되거나 큰 위협에 빠질 수 있다. 즉 튜너는 문제해결 능력을 심각하게 의심받게 된다.

검증은 가설로부터 추정되는 이미 발생한 다른 현상을 찾아내거나 재현함으로써 가능하다. 검증은 문제 해결에서 가장 시간이 많이 소요되며 가설 수립과 마찬가지로 경험과 지식이 필요하다. 하나의 가설로부터 추정될  있는 현상들은 여러 가지일  있으며 이러한 현상을 많이 생각해 낼수록 검증 시간은 단축될  있다.

검증된 가설은 새로운 팩트로 편입된다. 가설이 FACT 확정되면 이를 기반한 새로운 현상들도 유추될  있으며, 새로운 가설 수립을 위한 Input으로 활용된다.

이렇게 현상/팩트->가설->검증을 반복해 감으로써 최종적으로 문제의 근본원인을 찾아간다.

1.2 RR다이어그램

그런데 해결해야  문제가 한가지가 아닌 경우가 많고 포괄적인 경우에는 근본 원인 또한 한가지가 아니고 여러 가지가 존재할  있다. 이때는 모든 문제를 해결하였는지를 증명할 필요가발생하게 되는데 이때 사용하는 툴이 RR(Reason and Result)다이어그램[1]이다 RR다이어그램은 원인과 결과의 주종관계를 도식화하는 것이다.



먼저 REASON RESULT 증명된 가설에서 도출된다. 예를 들어 “IIOP 통신 때문에 CPU사용량이 높다라면 “IIOP 통신 REASON이되고 “CPU 사용량이 높다 라는 것은 RESULT 된다.

 검증된 가설들이 RR다이어그램으로 도식화되고 나면  다음에는 수집된 다른 현상들을 RR다이어그램에 추가하여 주종관계를 연결한다.



RR
다이어그램에서 결과 A” 처럼 어떠한 결과는 다른 결과를 유도하는 원인으로써 역할을 수도 있다. 그래서 모든 현상들은 원인으로부터 유도되어야 한다.

그런데 현상D”처럼 어떠한 REASON 연결되지 않은 RESULT 존재하는 경우가 있는데 그것은 아직 해결하지 못한 문제가 존재한다는 것을 의미한다.  많은 노력을 통해 원인 Y” 찾아야 한다.

RR다이어그램은 복잡한 문제의 현상과 결과들에 대한 상관관계들을 도식화 함으로써 이해당사자들이 문제의 원인과 결과를 쉽게 공유할  있게 한다.


[1] RR Diagram created by 정식



Posted by sjokim
,

자바에서는 개발자가 프로그램에서 별도로 메모리 관리를 하지 않는다. 이것은 C/C++에서는없던 획기적인 것이었다. 자바의 메모리 관리 개념은  개발자를 열광케 하고, 나아가 자바가 세상을 지배하는 언어가 되는데 핵심 역할을 담당하였다

그러나 애석하게도 자바에서는 여전히 메모리 문제가 발생하고있다. C/C++처럼 빈번하지는 않지만 종종 OutOfMemoryError 발생하고 있으며, 이러한 메모리 부족 에러는 운영자나 개발자가 가장 껄끄러워하는 문제 중에 하나로 인식되어있다.

1.1 자바의 메모리 부족 유형

Out Of Memory Error 발생하는 원인을 보면 크게 (1)단지 메모리가 부족할  (2)Heavy 서비스가 수행되면서 혹은 (3) 메모리 LEAK 의한 메모리 부족 때문으로 구분할  있다.

절대적인 메모리 부족

단지 메모리가 부족하다는 것은  설정된 메모리량이 요구되는 메모리량에 비해 부족하다는 것이다. 프로그램이나 기타 오류가 아닌 단지 값이 적게 설정되었다는 것을 의미하기 때문에 통상적으로는 -Xmx값을 늘려줌으로써 해결되는 것이 보통이다. 실제로는 의외로 JVM 시작시 메모리 옵션을 빠뜨리는 경우가 많다. 혹은 -Xmx256 같이 메모리 단위(원하는 설정-Xmx256m) 빠트리는 경우도 있다.  물론 옵션을 잘못 기술하는 것은 단순한 실수이지만, 자바  메모리에 대한 경험이 전혀 없어서  단위 시간당 서비스 호출건수(Service Arrival Rate) 비해  없이 적은량의 메모리를 지정하는 경우도 종종 있다.

SUN/HP JVM에서는 perm 영역이 작아서 발생하는 경우가 있다. 메모리의 perm영역에는 클래스코드 등이 저장되는 공간으로  사용되는 클래스가 많은 경우에는 사이즈를 늘려 주어야 한다.

Heavy Application Service 의한 부족

OutOfMemoryError  응용서비스(ex Web Request 처리 로직) 순간적으로 메모리를 과도하게사용함으로써 발생할  있다.

데이터 베이스에서 너무 많은 데이터를 로딩하거나 검색 조건이 잘못되어 검색서버에서 너무많은 텍스트를 조회하는 경우가 해당된다.  다른 경우로 과거에 upload/download프로그램에서 자주 발견되던 것으로 byte[] buffer에서 buffer 크기를 너무 크게 설정함으로써 연속공간부족 현상(IBM JVM) 발생하는 경우나,  동시에 여러 개의 요청이 발생하여 단위 시간당 절대사용량이 많아 OuOfMemory발생하는 경우를 생각할  있다. 물론 후자의 경우는 application정상적으로 메모리를 많이 사용하는지 단지 프로그램 오류인지는 판별하기 어려울 수도 있다.

LEAK 의한 메모리 부족

마지막으로 Memory Leak 발생하여 메모리가 부족해지는 경우이다.  보다 정확하게 자바에서메모리 LEAK 로직적으로 사용되지 않는 객체가 GC  없는 strong reference 의해 참조되어 메모리 사용량이 증가하는 상태를 말한다. 대부분 적절한 반환을 거치지 않아 발생한다.

대표적으로 JDBC관련 클래스를 사용하고 close() 호출하지 않게 되어 발생하는 경우를 생각할  있다(물론 JDBC 따라서 혹은 Web Application Server 따라서 메모리 Leak 발생하지 않을   있다.)

메모리 LEAK 다른 사례로 Cache 구현 로직에 문제가 있는 경우이다. CACHE에서 불필요한데이터의 제거 로직이 정상적으로 동작하지 않는 경우 OutOfmemoryError 발생할 수있다.

Http Session에서 데이터가 증가하는 현상 또한  범주에 포함 시킬  있을 것이다.

 

1.2  OutOfMemoryError 발생시 원인 분석

화면이나 프로그램 로그에서 OutOfMemoryError 보게 된다면 어떤 경우에 발생하는지를 정확히 판별해야 한다.

단지 설정이 잘못된 경우라면 통상적으로 JVM startup 혹은 startup이후 짧은 시간내에OutOfMemory 발생하게된다. 따라서 서버를 리스타트   OutOfMemoryError 보게 된다면 옵션 설정을 먼저 의심해 보아야 한다. 그러지만 PERM영역이 부족한 경우에는 약간 시간을두고 발생하게 되지만 특징은 HEAP메모리가 부족하지 않는데 OutOfMemoryError 발생하면서 SUN/HP JVM이라면  PERM영역이 부족하지 않은지를 먼저 확인해야  것이다.

만약 (2)경우라면 어떤 현상이 관찰될까? HEAP MEM 그래프를 보면 갑자기 메모리 사용량이급격히 증가하고 GC 빈번해지는 현상이 관찰되는 것이 일반적이다. 시간에 따라 메모리 사용량이 증가하지 않고 어느 순간에 메모리 사용량이 급격히 증가하고 GC 빈번해 지는 현상이발생한다면 특정 Application 메모리를 과도하게 사용함을 추정할  있다. 다만 Active Service 증가한 이후에 Memory사용량이 증가하고 GC 빈번해지면 인과관계가 약간 불분명할 수는 있다  다른 원인에 의한 Active Service 증가하고  service들이 사용하는 메모리량이 많아서 OutOfmemoryError 발생할 수는 있는데 사실 이런 경우는 빈번하지 않다.

IBM JVM 경우에 HEAP 여유가 충분하고 GC 빈번해지지도 않으면서 갑자기OutOfMemoryError 발생한 경우에는 fragmentation 의한 연속공간부족을 의심할  있다.

마지막으로 메모리 LEAK HEAP그래프가 시간에 따라 증가되는 현상으로 나타난다. 시간이 몇시간인 경우도 있으나  달이 넘는 경우도 있다. 메모리 사용량은 명시적으로System.gc() 호출한  비교해야 한다.

단지 설정이 잘못되거나 너무 적은 메모리를 설정한 경우에는 설정을 수정함으로써 해결하면OK이지만 특정 Application 의한 OutOfmemoryError Memory leak 발생하는 경우에는 해결을 위해 보다 논리적 접근이 필요하다.

특정 application 의한 불특정 시점에 OutOfMemoryError 발생하는 것이 확인된다며 어떤application Memory Error 발생하는지를 찾아야 한다. 만약 해당 Application uploaddownload 관련있는 프로그램이라면 데이터를 제어하기 위한 버퍼 사이즈를 먼저확인하고단순히 DB 사용하는 프로그램이라면 DB Access 데이터 량을 확인하는 것이 먼저이다.

 제니퍼는 OutOfMemoryError 의한 서비스 종료가 발생하면 WARNING 발생하고 에러 정보를 저장함으로 이것을 확인하는것도 방법이다. 통상적으로 메모리를 과도하게 사용한Application 수행되면 순간적으로 해당 인스턴스의 응답시간/CPU사용량등이 증가하게되며XVIEW상에서 모든 프로그램의 응답시간이 급격하게 증가하는 현상을 관찰할 수있는데 이때가장 높은 (응답시간이 길거나/CPU사용량이 높음) 위치하는 것이 문제의 Application 경우가 많다. 따라서 일자별 XView 데이터 조회를 통해서 해당 시간대를 면밀히 관찰하면 쉽게 찾을  있다.

Memory Leak 이것은 원만큼 자바 튜닝이 공력이 붙지 않으면 해결하기 힘들다  시간이 필요한데다가 개발 서버에서는 좀처럼 재연되지 않기 때문에 특히 어렵다. 메모리 릭은 원칙적으로HEAP DUMP 분석하는 것이 가장 빠른 길이다.

과거 JAVA 1.4 에서는 IBM JVM에서만 HEAP DUMP 가능했지만  JAVA1.5이상에서는 모든플렛폼에서 HEAP DUMP 가능하다.

 제니퍼에서는 HEAP 사용량을 모니터링 하고 트랜잭션별 응답시간과 CPU사용량을 모니터링함으로써 메모리 문제 해결에 크게 도움이  수있다.

제니퍼를 통해서 OutOfMemoeyError 어떠한 유형인지를 판별하고 만약 LEAK 의심이 된다면 언제쯤 OutOfMemoryError 발생할지 그리고 그메모리 부족이 서비스 응답시간에 영향은없는지를 모니터링 하여 안정적으로 시스템을 운영하면서 메모리 문제를 해결할  있다.

 



Posted by sjokim
,

서비스의 성능과 그 상세 내역(프로파일)을 추적하는 것은 서비스 중심 프로파일링이라 하고 Java EE컴포넌트(즉 서블릿, EJB JDBC)단위로 성능과 그 상세내역(프로파일)을 추적하는것을 컴포넌트 중심 프로파일링이라 한다.



Service Base Profiling

서비스의 처리 로직을 상세하게 추적한다.  모든 프로파일 정보를 서비스 단위로 맵핑한다.서비스 단위로 프로파일 정보를 확인할 수 있다.


Component Base Profiling

프로파일 정보를 컴포넌트 단위로 수집한다. 따라서 프로파일 정보를 컴포넌트 단위로 확인할 수있다. 만약 서비스에 대한 프로파일 검토가 필요하면 서비스가 호출한 컴포넌트를 확인하고 이 컴포넌트의 프로파일을 확인한다.


※컴포넌트 기반 프로파일링의 문제

컴포넌트 기반의 프로파일링은 얼핏 보면 논리적이고 서비스 기반 프로파일링 보다 자세한정보를 보여줄 것 같다. 하지만 컴포넌트 기반 프로파일링은 컴포넌트의 특성 때문에 비효율적인 서비스 모니터링 방법이다.


컴포넌트의 수행시간의 대부분은 여전히 JDBC혹은 TP와 같은 외부 호출이다.

컴포넌트 기반의 프로파일링의 이유의 핵심은 성능 저하 원인을 SQL이나 TP호출 보다는 어떤 Java EE컴포넌트에서 기인할 것이라는 가정하기 때문이다.

하지만 실제 프로덕션 환경에서 성능저하의 원인인 대부분 외부 시스템 즉 SQL/TP/LDAP호출에서 기인하는 경우가 더 많다.. 

그래서 컴포넌트 중심 프로파일링을 하게되면 컴포넌트 단위의 프로파일을 보고 그것이 서비스에 어떻게 영향을 미쳤는지를 알기 위해서는 다시 서비스 프로파일을 보아야 한다. 즉 서비스->컴포넌트, 다시 컴포넌트->SQL/TP의 2중의 프로파일을 분석해야 한다.


서비스와 컴포넌트간의 맵핑을 해야하고 서비스와 SQL/TP 간의 맵핑은 어렵다.

컴포넌트는 서비스와 N:M관계이다  또한 컴포넌트와 SQL/TP관계도 N:M관계이다. 그리고  컴포넌트간의 호출관계도 발생한다 그만큼 그들간의 맵핑 정보는 복잡해지고 추적과 분석이 어려워 진다.


운영 담당자는 컴포넌트를 잘 모른다

어쩌면 이것이 가장 큰 문제 일수있다. 일반적으로 운영담당자는 Java EE의 전문가가 아니다. 개략적인 이해만 있을 뿐이다. 설령 JavaEE에 지식이 풍부하더라도 운영담당자가 개발에 참여하는 경우는 거의 없다. 당연히 운영 담당자는 애플리케이션 내의 컴포넌트 구성이나 상관관계에 대한 깊은 이해가 어렵다. 또한 이들에게는 Application Server Tier의 진입점인 서비스 로부터 끝지점인 DB/TP 연계 중심으로 성능을 이해하는 것이, EJB나 Servlet/JSP, JMS 등과 같은 컴포넌트 구성을 이해하는 것이 보다는 쉽다.

당연히 이들은 느린 서비스를 추출하고 그것의 수행내역을 개발자에게 검토 요청하는 것이가장 효과적일 것이다.


오버헤드를 피할 수 없다.

애플리케이션 서비스를 프로파일링해 보면 프로파일링 자체의 오버헤드도 있지만, 프로파일링정보의 목록을 관리하는 오버헤드도 크다. 그런데 컴포넌트 단위의 프로파일링에서는 각 컴포넌트 별로 프로파일링 목록을 관리해야 하기 때문에 프로파일링 목록이 엄청나게 많아진다.

그렇다고 프로파일링 컴포넌트를 필터링하게되면 분석정보의 유실이나 왜곡을 피할 수 없다. 

'성능과 장애' 카테고리의 다른 글

Application Monitorability을 위한 설계 고려사항  (0) 2009.10.27
문제 해결을 위한 TOOLS  (0) 2009.10.26
OutOfMemoryError 해결  (0) 2009.10.26
XVIEW를 만들게된 동기  (0) 2009.10.26
성능 테스트 관련 용어  (0) 2009.10.26
Posted by sjokim
,


서비스 트랜잭션을 직관적으로 모니터링하자 그래서 XView를 만들었다

애플리케이션 모니터링을 처음 고민하기 시작할때가 
아마도 처음 장애해결에 나갔을 때 인것 같다.
DB,H/W,N/W,그리고 나(APP) 그렇게 4명이 시스템의 장애를
해결하기 위해 사이트에 나간적이 있었다.

첫날 사이트에 도착해서 이런저런 회의를 통해서 
문제가 심각하다는 이야기를 듣고 각자 하루 동안 현상을 수집하기로 했다
DB는 SQL툴을 열어 놓고 SQL문을수행하면서 결과를 수집하기 시작했다.
H/W는 수십개의 쉘을 돌리면서 결과를 수집하기 시작했다.
N/W담당자도 쉘과 몇개의 프로그램을 설치하고는 정보를 수집하였다.
그런데 나는(?) 다른 사람들은 운영서버에서 정보를 수집하는데
나는 개발자에게 소스를 받았다. 그리고는 소스를 읽어나갔다.

다음날... 4명은 탁자에 모였다.. 나를 제외한 모두는 
그래프를 들고서 다른 사람에게 현황을 설명하기 시작했다.
DB도 H/W도 N/W도 그런데 나는 그자리에서 나만 이해하는
소스 코드들을 들고 어쩔줄 몰라했다.. 그 많은 소스 중에서
문제가 쉽게 발견되지 않는 것이 당연하기는 했다..

어쨌거나.. 그때 나에게도 뭔가 툴이 필요하다고 느꼈다..
뭔가 빨리 깔아서 잠깐 모니터링 하고 다음날 이야기 할 수 있는
그런툴.. 문제를 빨리 잡을 수 있는 툴 그런것이 필요했다.

결과적으로 그 사이트의 문제는 EJB 프로그램을 잘못해서
메모리가 급격히 증가하고 그래서 발생한 문제 였다.
정말 운이 좋아서.. 우연히 전혀 비과학적으로 3일째 소스를 넘기다가 우연히 발견하여
문제를 해결하였다..
이런경우 우리는 "소 뒷발로 쥐잡았다"고 한다.

그런데 이러한 나의 고민은 이후에도 계속되었다.
몇개의 사이트에 문제 해결을 나가는 동안
나는 로그와 소스에만 의존해야 했다.
하드웨어의 로그는 구글에서 검색하면 대부분 나온다.
그러나 애플리케이션이 남기는 로그 인터넷 어디에도 없다 그사이트에만 있는 로그이다.
그렇게 힘들게 몇개의 시스템 문제해결에 참가한 후에

상용 툴을 설치해야 겠다고 생각하게되었다.
지금도 있는 몇개의 툴을 설치했다. 아니 정확하게는 
설치를 시도했다.. 하지만 일반적으로 나에게 주어진 시간은
2~3일 정도 그시간이 지나면 모든 사람은 내얼굴을 보면서
빨리 문제를 해결할 것을 종용한다.
나는 툴 설치를 포기하고 다시 로그와 소스에 의존하여
문제를 해결하였다.

그리고 나서는 안되겠다. 내가 필요한 것을 내가 만들어야 겠다고 생각했다
막상 툴을 만들려고 하니..
애플리케이션을 모니터링하려면 어떻게 해야할까..
아니 정확히는 무엇을 모니터링 할까 하는 원론적인
질문이 고민스러웠다.
CPU,MEM 이런것은 시스템 모니터링 툴들이 알려준다
SQL성능 이것은 DB가 잘 알려준다.
그러면 나는? 애플리케이션을 모니터링 해야 한다.
그런데 Application Server에 동작하는 프로그램은
모양이 비슷하다 사용자(브라우저) 요청을 받아서 결과를 리턴한다.
그 결과를 만들기 위해 DB도 가고 턱시도도 호출하고...
우리는 이런것을 트랜잭션이라고 한다. 
아마 서비스 트랜잭션이 더 맞을 것이다.

그래 나는 이 트랜잭션을 모니터링 해야 겠다. 그때만 해도
프로파일 툴이 일반화 되지 않았지만 
트랜잭션 프로파일링이 필요하다는 결론에 이르렀다.
그래서 일단 트랜잭션 별로 프로파일 정보를 로그파일에 
남겼다. 로그파일 명에 서비스 명과 응답시간을 넣어서
디렉토리에서 쉽게 찾을 수있도록 하였다 물론 프로파일링 툴을 적용하면
이것을 툴에서 할 것이다.하지만 원리는 같다.

그런데 문제가 있었다. 트랜잭션성능과 구간별 시간은 보이는데 애플리케이션 전체를
알 수 없었다 그트랜잭션 하나의 문제가 전체의 문제라는 확신을 할 수가 없었다.

만약 트랜잭션 전체의 성능을 보면 애플리케이션을 알 수 있을텐데
볼 수 없었다. 나는 트랜잭션 프로파일 하나하나를 리뷰했지만
동일 서비스가 트랜잭션에 따라 다른 응답시간을 보이고
이것들의 원인을 정확히 알 수 없었고 그것이 문제의 원인이라고
주장할 수 없었다.

문제는 트랜잭션의 성능을 한눈에 볼필요가 있었다.
즉 문제 핵심은 그많은 트랜잭션(초당 몇백개)의 성능을
어떻게 볼 수 잇게 하느냐가 문제였다 나는 그중에서 프로파일을
분석해야할 트랜잭션을 선별하거나 트랜잭션 간의 연관도를 알고 싶었다

서비스명이 같은 트랜잭션 끼리 묶어서 평균 응답시간을
라인 그래프로 보기도 하고 리스트박스에 표현도 해보았지만
한눈에 모든 트랜잭션을 관찰한다는 것은 어려웠다.

그러다가 유래카..^^ 트랜잭션의 성능을 점으로 표현하면될 것 같았다.
프로그램을 만들어서 모든 트랜잭션을 점으로 화면에 표현하였다..
세로축은 응답시간 가로축은 종료시간으로한 점 그래프를 만들고
그 중에서 점을 선택하면 그 점에 대한 프로파일 정보를 
확인할 수있도록 하였다.

이렇게해서 제니퍼의 XVIEW가 만들어졌다.
XVIEW는 모든 트랜잭션을 한눈에 개별적으로 확인할 수 있다.
현재 어떠한 툴도 트랜잭션 모니터링을 이렇게 하지는 않는다.

XVIEW에서는 느린 서비스 혹은 같은 시간대에 수행된 트랜잭션들을 
직관적으로 확인하고 그들간의 상관관계를 확인할 수 있다

동일 서비스에 대해 느릴때와 빠를 때의 차이를 상대비교할 수있으며
트랜잭션간의 락이 발생하거나 자원의 부적이 응답시간에 어떻게
영향을 미치는지도 직관적으로 확인할 수 있다.

그뒤로 나는 애플리케이션 성능 바라보는데 한단계 수준 업이 되었다는 것을 느끼게 되었다.


Posted by sjokim
,

우리들 중 다수는 부하테스트(Load Test) 스트레스 테스트(Stress Test)의 용어의 차이를 잘 모른 채 그냥 동의어로 사용하는 경향이 있다. 이러한 용어의 명확한 구분 없이 사용하는 사이트의 경우는, 도대체 적절한 부하테스트를 하자는 것인지, 의미있는 스트레스 테스트를 하자는 것인지 목표가 명확하지 않는 경우가 대부분이다.

스트레스테스트(Stress Test)는 어플리케이션이 실행 시에 필요로 하는 각종 리소스(CPU, RAM, Disk )의 허용하는 한도를 넘어서서 비정상적인 높은 부하를 발생시켜보는 테스트를 일컫는다. 일정한 한도를 넘어서는 부하 상황이 되면 경우에 따라 JVM이 다운되거나, 데이터를 잃어버리게 되는 것 등과 같이 시스템의 비정상적인 작동을 유발시킬 수도 있다. 이 같은 결점(Bug)이나 결함(failure)을 찾기 위해 스트레스를 가해 보는 것이다. 스트레스 테스트 시의 부하(일련의 들어오는 요청)는 이처럼 시스템 리소스의 한계점을 시험하려는 의도이기 때문에, 다분히 의도적으로 왜곡되는 경향이 있으며, 향후 실제 접속자에 의해 발생하는 부하량 패턴과는 거리가 멀 수도 있다.

반면, 부하테스트(Load Test)는 적절한 부하를 발생시켜 통계적으로 의미있는 수치를 측정하는 테스트를 일컫는다. 부하테스트의 두 가지 중요한 목적 중 하나는 장시간 서비스 가능 여부를 확인하는 신뢰성(reliability) 테스트와 두 번째는 성능 테스트(Performance Test)이다. 부하테스트(Load Test)라는 용어 자체는 대단히 모호하며 그 용어를 의미있게 사용하기엔 너무나 일반적이고 미흡한 면이 없잖아 있다. 예를 들어 부하(Load)라는 것이 과부하(Overload) 높은부하(High Load)를 암묵적으로 항상 의미한다고 생각하는가? 성능테스트(Performance Test) 관점에서의 부하(Load)는 최소레벨(0 tps)에서부터, 리소스 고갈 상황이나 기형적인 응답시간의 극심한 저하 혹은 트렌젝션 실패 등과 같은 상황이 발생하기 직전까지의 최대 레벨(Maximum tps)까지 다양할 수 있다.

성능테스트(Performance Test)는 부하테스트 중 하나의 관점, 즉 성능적 관점만 측정하겠다는 뜻이 담겨 있다. 해당 시스템 혹은 어플리케이션의 성능을 측정한다함은 점진적인 부하량 증가 과정에서 더 이상 단위시간당 최대 처리량(TPS)이 증가하지 않을 때, 그 때의 수치를 측정하고 그 수치를 해석하는 과정을 의미한다. 성능테스트의 일반적인 목적은 현재의 시스템 혹은 어플리케이션이 최대로 수용가능한 동시단말사용자수가 몇 명인지, 혹은 목표로 정한 성능이 도출되지 않을 때 병목지점이 어딘지를 밝히고 목표성능을 획득하기 위해 무엇을 시정해야하는지를 찾아내기 위함이다. 성능테스트 과정에서 매우 중요한 부분은 목표성능을 설정하고 그러한 목표성능을 확인/측정하기 위해 향후 시스템 운영 중에 실제로 발생할 접속사용자의 호출패턴이 어떠하냐를 분석/추정하는 과정이 반드시 필요하고, 이를 근간으로 점진적 부하를 발생시켜야 의미있는 성능테스트 결과를 도출할 수 있다. 그렇지 않을 경우 성능테스트가 자칫 스트레스테스트로 끝나고 만다. 

각 용어를 도식으로 표현하면 다음과 같다.



Posted by sjokim
,