SSISO Community

시소당

BEA 웹로직 튜닝 (1)

WAS는 단순히 도입만 했다고 해서 모든 것이 끝난 것이 아니다. 하드웨어, 운영체제, 네트워크, 데이터베이스 등 여러 다양한 환경과 관계를 맺고 있기 때문에 각 분야에 맞는 튜닝을 통해 보다 안정적이고 빠른 서비스를 만끽할 수 있다. WAS 중 하나인 BEA 웹로직 서버의 예를 통해 WAS의 튜닝 과정이 어떻게 이뤄지고 어떤 효과를 낼 수 있는지 소개한다.


역사적으로 보면 애플리케이션 서버라는 용어는 클라이언트/서버가 컴퓨팅 환경으로 채택되면서부터 사용됐다고 할 수 있다. 보다 구체적으로는 클라이언트/서버 환경이 2계층 구조에서 3계층 구조로 변화돼 가는 과정에서 비롯됐다고 할 수 있다.
3계층 구조에서는 사용자 프로그램에 대한 관리 기능을 제공하는 중간 계층인 미들웨어내에 주된 업무 로직이 이뤄지고 클라이언트 프로그램은 주로 그 결과를 포장해 보여주는 역할만을 하게 된다. 결국 기존의 2개 계층 사이에 미들웨어 층이 추가돼 3개의 계층을 이루게 된다.
이 미들웨어 계층은 사용자 애플리케이션에 대한 관리 기능 등을 제공하는 ‘애플리케이션을 위한 플랫폼’을 제공한다는 의미에서 ‘애플리케이션 서버’라고 불리어졌으며, 90년대 후반부터 비약적으로 발전한 인터넷 환경에서 미들웨어의 역할을 하는 애플리케이션 서버를 WAS라고 부르기 시작한 것이다.
BEA의 웹로직 서버(WebLogic Server)는 썬에서 제시한 J2EE 최신 표준을 준수하는 제품 중 하나로 하드웨어, 운영체제, 네트워크, JVM(Java Virtual Machine), 데이터베이스 등 전산환경에서의 거의 모든 부분과 관계를 맺고 있다. 때문에 보다 안정되고 빠른 서비스를 제공하기 위해서는 각 분야에 맞는 튜닝이 필요하다.
성능(performance)을 조사할 때는 우선 하드웨어의 사양과 환경설정을 고려해야 한다. 약간의 하드웨어 환경 설정은 웹로직 서버와 애플리케이션에 큰 영향을 줄 수가 있다.
여기서 가장 먼저 고려해야 할 사항은 해당 하드웨어와 운영체제가 웹로직 서버를 지원하는 지이다. 이는 웹로직 서버의 플랫폼 서포트 페이지에서 확인해야 한다.
또한 해당 플랫폼에 대한 상세한 튜닝은 각 플랫폼 별로 벤더에서 제공하는 매뉴얼을 참고하면 된다.
웹로직 서버와 관련된 대표적인 운영체제의 튜닝은 File descriptor, TCP 파라미터의 튜닝으로, 이를 통해 성능을 향상시킬 수 있다.

File Descriptor
File Descriptor는 주로 각 소켓 커넥션(Socket Connection)으로 사용되는데 File Descriptor의 제한에 의해 영향을 받는 경우는 보통 소켓을 부적절하게 사용하는 경우이지만, 그 외에도 다음과 같은 에러가 발생하기도 한다.

·Too many open files
·Broken pipe
·ClassNotFound

물론 Broken pipe 에러는 다양한 경우에 발생하는 에러이지만 File Descriptor의 제한으로 인해 발생할 수 있다. 소켓 이외에 디스크로부터 클래스를 얻어 로드하는 경우 File Descriptor가 사용되는데, 부족하면 해당 시스템에 클래스가 존재하고도 ClassNotFound와 같은 에러가 표시되기도 한다.
다음의 예는 솔라리스에서 File Descriptor를 설정하는 예이다.

·ulimit 커맨드를 사용해 File Descriptor을 확인한다.
·ulimit 커맨드를 사용해 현재 프로세서에서의 File Descriptor의 제한을 일시적으로 변경한다.
·File Descriptor의 값을 영원히 설정하기 위해 /etc/system 파일에 다음을 설정한다.

set rlim_fd_max=4096 /* hard limit */ (root 권한이 필요)

·웹로직을 다시 시작하면 (화면 1)과 같은 메시지를 볼 수 있다. 이때 주의할 점은 Default soft limit는 변경하지 않는다는 점이다. 이는 웹로직 서버에는 영향을 미치지 않으나 같은 서버에 있는 많은 다른 프로세스에 영향을 미칠 수 있기 때문이다.

TCP 패러미터의 튜닝
TCP 패러미터 뿐 아니라 플랫폼별로 많은 패러미터가 존재하지만 여기서는 윈도우의 TcpTimedWaitDelay와 솔라리스의 tcp_time_wait_ interval, tcp_conn_req_max_q, tcp_conn_ req_max_q0 등을 알아보도록 하겠다.
윈도우의 TcpTimedWaitDelay와 솔라리스의 tcp_time_wait_ interval은 커넥션이 종료됐을 때 TIME_WAIT 상태로 머물게 되는 시간을 설정한다.
이 값의 디폴트는 4분으로 짧은 시간에 많은 클라이언트가 접속을 하면 네트워크 성능에 영향을 줄 수 있기 때문에 60초로 변경할 것을 추천한다. 윈도우에서 TcpTimedWaitDelay를 설정하는 방법은 다음과 같다.

·레지스트리 위치 :
HKLM\System\CurrentControlSet\Services\Tcpip\Parameters
·유효한 범위 : 30∼300초
·디폴트 : 240초
·추천하는 값 : 60초

다음은 솔라리스에서 tcp_time_wait_interval을 설정하는 방법이다.

·기본 : 240000ms(240초)
·추천 : 60000ms (60초)
·패러미터 설정방법은 ndd 커멘드를 사용해 설정한다.
·ndd -set /dev/tcp tcp_time_wait_interval 60000
·tcp_time_wait_interval을 영구히 설정하기 위해서는 /etc/rc2.d/S69inet에 값을 설정한다.

솔라리스에는 클라이언트의 리퀘스트를 3웨이 핸드세이크(3-way handshake)를 통해 받는다. 여기에는 ICQ(Incomplete Connec tions Queue), CCQ(Completed Connections Queue)가 있는데, ICQ는 시스템에 전달되는 모든 SYN 패킷을 저장한다.
즉 처음으로 커넥션을 시도하는 리퀘스트(Request)는 일단은 여기에 머물고, 3웨이 핸드세이크를 통해 완벽하게 established 상태가 되지 않은 모든 커넥션에 대한 내용도 바로 이 큐(Queue)에 저장되는 것이다.
CCQ는 3웨이 핸드세이크를 통해 커넥션이 성립된 것들이 저장되는 큐다. 즉 CCQ에서 대기하면서 다시 accept를 호출 하는 것을 기다리고 accept된 것들은 큐에서 사라진다.
모든 큐는 설정된 값(기본 128개)에 의해 제한을 받는데 어떤 이유에서든 CCQ에서 지워지지 않고, 큐가 꽉 차면 커널은 더 이상의 커넥션을 받지 않는다.
타임아웃(Timeout) 값은 큐에 저장된 SYN 세그먼트에 의해 결정되며, 큐에 저장된 SYN 패킷에 대해 ACK가 수신되지 않는 경우(SYN_RCVD 상태)에는 시간이 경과되고 그 결과 그냥 패킷이 지워진다. 결과적으로 클라이언트가 아무리 SYN를 보내도 이러한 커넥션은 ICQ에 머물게 되며 3웨이 핸드세이크를 하지 않으므로 CCQ로 넘어가지 않는다. 이런 이유로 인해 두 개의 큐 설정 값은 웹로직 서버의 성능에 큰 영향을 주게 된다.

[Incomplete Connections Queue: tcp_conn_req_max_q0 ]
·기본 : 1024
·추천 : 1204 이상
·패러미터 설정방법은 ndd 커멘드를 사용해 설정한다.
·ndd -set /dev/tcp tcp_conn_req_max_q0 1024
·tcp_conn_req_max_q0을 영구히 설정하기 위해서는 /etc/rc2.d/S69inet에 값을 설정 한다.

[Completed Connections Queue: tcp_conn_req_max_q ]
·기본 : 128
·추천 : 128 이상
·패러미터 설정방법은 ndd 커멘드를 사용해 설정한다.
·ndd -set /dev/tcp tcp_conn_req_max_q 128
·tcp_conn_req_max_q을 영구히 설정하기 위해서는 /etc/rc2.d/S69inet에 값을 설정한다.

JVM 튜닝하기
JVM(Java Virtual Machine)은 프로세서 상에서 자바 클래스 파일의 바이트 코드를 실행하는 실행 엔진이다. JVM 튜닝은 웹로직과 애플리케이션의 성능에 큰 영향을 준다.
특히 JVM의 벤더와 버전은 성능에 큰 영향을 주므로 웹로직 서버에서 실행되는 것이 보증된 JVM을 사용해야 한다. 웹로직 6.x에서는 1.3.x 버전을 준수한 JVM을 지원하고 있다.
JVM 힙(heap)은 현재 사용되는 오브젝트, 사용되지 않는 오브젝트(non-referenced objects), 이용 가능한 여유 메모리로 구성되는데, 이런 JVM 힙 사이즈에 의해 GC(Garbage Collection : 사용되지 않는 오브젝트를 de-allocating)를 하는 빈도와 시간이 결정된다.
GC를 하고 있는 동안 JVM은 프로세스를 실행할 수 없기 때문에 성능이 저하된다. GC의 적절한 실행빈도는 애플리케이션에 따라 다르므로, GC의 실제 시간과 빈도를 해석해 조정할 필요가 있다.
큰 힙 사이즈를 설정할 경우, GC 전체는 저속화되지만 실행빈도가 낮아지면 메모리의 요구에 맞게 힙 사이즈를 설정할 경우, GC전체는 고속화되지만 실행빈도가 높아진다. 힙 사이즈의 튜닝의 목적은 소정의 시간에 처리할 수 있는 클라이언트의 수를 최대한으로 늘리면서 GC의 실행시간을 최소한으로 억제하는 것이다. 힙 사이즈의 결정은 다음과 같은 사항에 따라 하면 된다.

·애플리케이션 실행 중에, 최대의 부하를 준 상태로 웹로직 서버의 성능을 모니터 한다.
·-verbosegc 옵션을 사용해, GC에 투입될 시간과 자원을 정확하게 측정한다.
·JVM의 verbose에서 GC 출력을 유효하게 해서 표준 에러와 표준 출력을 로그 파일에 기록 한다.
·weblogic.log 파일에서 GC 전후의 타임 스탬프를 비교한다(GC전체 실행시간이 3∼5초를 넘기지 않도록 한다).
·평균 메모리 점유량(각 GC 실행 후의 힙 상태)에서 힙의 여유가 항상 85%가 되는 경우, 힙 사이즈를 작게 해도 괜찮다.
·Java HotSpot JVM 1.3 을 사용하고 있는 경우는 제너레이션(Generation)의 사이즈를 설정한다.

http://e-docs.bea.com/wls/docs61/perform/JVMTuning.html#1109778

예) $java ... -XX:NewSize=128m -XX:MaxNewSize=128m
-XX:SurvivorRatio=8 -Xms512m -Xmx512m ...

·힙 사이즈는 시스템에서 사용 가능한 여유 메모리보다 작게 한다. 즉 페이지가 디스크에 스왑되지 않는 범위로 설정한다.
·시스템이 GC에 소비하는 시간이 너무 긴 경우 힙 사이즈를 작게 한다. 일반적으로 사용 가능한 RAM의 80%를 JVM에 할당한다.
·성능 향상을 위해 최소 힙 사이즈와 최대 힙 사이즈는 같게 설정한다.

웹로직 서버의 튜닝
웹로직 서버를 튜닝하는 방법은 실행 쓰레드(thread), 성능 팩, 소켓리더, 커넥션 백로그 버퍼링(Connection Backlog Buffering), JDBC 풀의 튜닝 등이 있다. 모든 설정은 웹로직 서버의 콘솔을 이용해 변경할 수 있고 튜닝된 정보는 config.xml에 저장된다.

·실행 쓰레드의 설정
웹로직 서버의 쓰레드는 애플리케이션 작업의 처리와 리퀘스트를 대기(listen)하는 두가지 목적으로 사용된다. 웹로직의 쓰레드 풀은 쓰레드의 총 수를 설정해 할당할 수 있는데, 기본적인 실행 쓰레드 값은 15이다.
대부분의 애플리케이션은 이 값을 변경할 필요가 없다. 이 값이 너무 크면 메모리 사용량이 커져 컨텍스트의 스위칭이 증가해 성능이 저하된다.
응답(Response)에 많은 시간이 걸리는 DB 호출을 하는 경우는 반대의 경우 보다 많은 실행 쓰레드가 필요하다. 후자의 경우는 적은 실행 쓰레드로 성능을 향상시킬 수 있다. 또한 쓰레드 수가 너무 적은 경우, 웹로직 서버가 최대 부하로 동작하면 CPU의 능력을 100% 활용할 수 없다.

서버선택 > 마우스 우측(View Execute Queue) > 실행 큐 선택 > 쓰레드 설정 값 설정

·퍼포먼스 팩의 사용
많은 벤치 마크 결과 플랫품에 맞는 퍼포먼스 팩을 사용하면 성능이 최대 3배까지 향상되는 것으로 입증 퍼포먼스 팩은 플랫폼용으로 최적화된 네이티브 소켓 멀티 플렉서(platform-optimized native socket multiplexor)를 사용해 성능을 향상시킨다.

서버선택 > Configuration > Tuning > Enable Native IO 체크를 통해 설정

·소켓 리더 쓰레드 튜닝
소켓으로부터 메시지를 읽어들이는 실행 쓰레드의 최고 비율을 설정할 수 있다. 이 값은 퍼포먼스 팩을 사용하지 않을 때만 설정할 수 있고 추천값은 30이다
서버선택 > Configuration > Tuning > Socket Readers 값을 설정

·커넥션 백로그 버퍼링 튜닝
커넥션 백로그는 대기 큐에 들어온 TCP 커넥션의 수를 지정한다. 이 고정 사이즈의 큐에는 TCP 스택에서는 수신됐지만, 애플리케이션에서는 아직 받아 들여지지 않은 커넥션 리퀘스트가 들어있다. 디폴트는 50이고, 최대치는 운영체제마다 다르다.
클라이언트가 리퀘스트를 요청했으나 Connection refused라는 메시지를 받고, 서버에서는 아무런 에러가 없다면 이 값을 디폴트로부터 25%를 크게 하고, 이런 메시지가 표시되지 않게 될 때까지 이 속성 값을 25%씩 증가시키면서 테스트한다.

서버선택 > Configuration > Tuning > AcceptBacklog 값을 설정

·커넥션 풀 튜닝
DBMS에서 JDBC 커넥션을 얻는 것은 매우 시간이 많이 걸리는 작업이다. JDBC 애플리케이션으로 DB 커넥션의 오픈(open)과 클로우즈(close)를 반복할 필요가 있는 경우, 이것은 성능의 문제가 된다.
웹로직 서버를 시작시키면 커넥션 풀 내의 커넥션이 오픈돼 모든 클라이언트가 사용할 수 있게 된다. 클라이언트가 커넥션 풀의 커넥션을 클로우즈하면 그 커넥션은 풀로 되돌려져 다른 클라이언트가 사용할 수 있는 상태가 된다. 즉 커넥션 그 자체가 클로우즈되는 것이 아니다.
커넥션 풀을 설정시 초기값(InitialCapacity)과 최대값(MaxCapacity)을 설정할 수 있는데 개발시에는 초기값을 작게 설정하면 서버의 기동이 빠르기 때문에 편리하다. 하지만 운영체제에서는 서버에 부하가 걸리면 가능한 한 빠르게 서비스를 해주기 위해서는 모든 자원이 프로세스의 처리에 소비된다. 따라서 초기값과 최대값을 같게 설정하여 모든 자원이 프로세스 처리에 사용되도록 한다.
운영 시스템에서는 풀 내의 커넥션 수를 JDBC 커넥션을 필요로 하는 동시 사용자의 세션수와 같게 하는 것을 추천한다. JDBC 드라이버 및 DBMS에 따라서 가능한 물리적 커넥션수가 제한돼 있는 경우도 있다.

서버선택 > Configuration > Tuning > AcceptBac klog 값을 설정

·멀티 CPU 머신에서의 튜닝
멀티 CPU(Multi-CPU)를 탑재한 머신에서는 사용 가능한 CPU에 웹로직을 클러스터로 구성하는 것을 고려할 필요가 있다. 서버에 대한 CPU의 비율을 결정하려면, 네트워크 요건과 디스크 I/O 요건을 검증해봐야 한다.
웹 애플리케이션이 주로 네트워크 입출력인 경우에는, 보다 고속의 NIC를 설치하는 것이 CPU의 추가 보다 높은 성능을 얻을 수 있다. 이것은 대부분의 CPU가 이용 가능한 소켓의 리드(Read)를 기다리는 동안 아이들(Idle) 상태이기 때문이다.
웹 애플리케이션이 주로 디스크 입출력의 경우에는, CPU의 추가 전에 디스크의 스핀들(spindle) 또는 각각의 디스크와 컨트롤러를 업그레이드하는 것을 생각해 볼 필요가 있다. 즉 추가의 CPU를 할당하기 전에 웹 애플리케이션이 네트워크 또는 디스크 입출력보다 CPU 바운드 인지를 확인해야 한다. CPU 바운드의 경우 1개의 웹로직 인스턴스에 CPU 사용률이 거의 100%라면 서버에 대한 CPU 비율을 증가 시킨다. 웹 애플리케이션에 필요한 처리는 다르지만, BEA의 조사결과 2개의 CPU에 대해 1개의 웹로직 인스턴스로 한 비율의 경우에 최적의 결과를 얻을 수 있었다. 

3753 view

4.0 stars