본문 바로가기

실제 아키텍처

Troubleshooting response time problems – why you cannot trust your system metrics

원제 : Troubleshooting response time problems – why you cannot trust your system metrics

번역 : 응답시간 문제 해결 - 왜 시스템 측정을 신뢰하지 못하는가?

Production Monitoring(제품 감시) 은 시스템의 안정성과 건강함을 확신하는 것인데, 응용프로그램도 포함합니다. 많은 시간 우리는 안정적인 시스템이 안정적이고 건강한 응용프로그램을 이끈다고 가정하는, 시스템 모니터링은 견고한 상용화 시스템을 맞닥뜨렸습니다. 이제 시스템 모니터링이 응용프로그램(Application)에 대해서 무엇을 말해주는지 살펴봅시다.

매우 간단한 2티어 웹 응용프로그램을 봅시다.


 

단순한 멀티-티어 전자상거래 솔루션입니다. 사용자는 검색을 할때 나쁜 성능을 염려합니다. 성능이 불만족스러울 때 무엇을 찾을 수 있는지 봅시다. 간단한 측정(metric) 2개를 살펴보면서 시작합니다.

CPU 활용도(CPU Utilization)

가장 잘 알려진 운영체계 측정은 CPU 활용도인데, 매우 잘못 이해되고 있습니다. 이 측정은 최근에 코드를 실행하기 위해 CPU를 얼마나 사용했는가와 이론적으로 얼마나 더 실행할 것인지를 알려줍니다. 다른 활용도 측정처럼 건강, 안정성 또는 성능이 아니라 용량에 대해서만 알려줍니다. 간단하게 put: 99% CPU 활용도는 최상이거나 응용프로그램때문에 재앙이 지연되고 있음을 지시합니다.

The CPU Usage of the two tiers

CPU 차트는 양쪽 티어에서 모두 부족함이 없음을 보여줍니다.

우리의 시작점을 살펴봅시다. CPU 활용도는 100% 아래면 좋은 것이고, 따라서 용량이 남아있습니다. 그러나 장비 또는 응용프로그램이 건강하다는 의미일까요? 작업에 더 어울리는 부하평균(Load Average)을 살펴봅시다(System\Processor QueueLength on Windows). 부하 평균은 얼마나 많은 쓰레드나 프로세스가 현재 실행되고 있거나 CPU를 사용하기 위해 기다리고 있는지 알려줍니다.

Unix Top Output: load average: 1.31, 1.13, 1.10

Linux 시스템은 마지막 1분, 5분, 15분에 대한 세 개의 부하 평균을 표시합니다. 위에서 보여준 출력은 마지막 1분에 동시에 CPU 코어를 필요로 하는 평균 1.3 프로세스가 있다는 것을 보여줍니다.

부하 평균이 시스템의 코어 숫자보다 높다면 100% CPU 활용도에 이르렀거나, 또는 시스템은 CPU를 최대한 소비하는 것이 아닌 다른 자원을 기다려야 하는 상황임을 알 수 있습니다. 스왑이거나 다른 I/O 연관된 작업들인 것이죠. 부하 평균은 한편으로는 CPU 사용량을 신뢰할 수 있지만 다른 한편으로는 장비가 부하를 넘어섰다는 것을 알려줍니다. 부하 평균은 응용프로그램이 얼마나 잘 수행하고 있는지 말해주지 않고, CPU의 부족이 부정적인 영향을 줄지에 대해서 알려줍니다. 문제를 주목했다면 이슈를 만든 원인이 아니라, 이슈를 만든 응용프로그램을 식별할 수 있습니다.

우리 사례에서 부하 평균이나 CPU 사용량 어떤 것도 우리의 성능 이슈를 밝혀주진 못했습니다. 높은 CPU 활용도나 높은 부하 평균을 목격한다면 우리는 CPU에 부족이 있다고 가정할 수 있지만, 확신할 수는 없습니다.

메모리 사용량(Memory Usage)

메모리 부족이 시스템 비안정화를 이끌기 때문에 사용 메모리를 감시합니다. 주의할 중요한 사실은 Unix와 Linux 운영체계는 언제나 100% 메모리 활용도에 가깝게 보여준다는 것입니다. 이들 운영체계는 버퍼와 메모리가 필요하다면 swapped out에 반대되는 폐기를 얻는 캐시로 메모리를 채웁니다. "real(실제)" 메모리 사용량을 얻으려면 뽑아내야 합니다. Linux에서는 free 명령어를 사용합니다.

Memory Usage on the two systems

두 시스템에서 메모리 사용량은 둘다 문제가 없습니다

 

메모리가 충분하지 않다면  프로세스의 상주하는 메모리 사용량을 주시하여 어떤 응용프로그램이 대부분의 메모리를 사용하는지 밝혀야 합니다. 한 번 밝혀지면 다른 도구를 사용하여 왜 프로세스가 메모리를 사용하는지 아니면 정상적인지 밝혀야 합니다. Java/.NET 성능에 대한 메모리를 살펴볼 때 응용프로그램이 절대로 swapped out을 하지 않는다는 것을 명심해야 합니다. Java가 random-access 방식으로 자신의 모든 메모리에 접근하기에 특별하게 중요합니다. 메모리 부분이 스왑되면 성능 감소가 발생합니다. 프로세스에 있는 스왑핑 측정으로 모니터링할수 있습니다. 여기서 배우려는 것이 메모리 부족이 응용프로그램 성능에 부정적인 영향을 주는가 입니다. 이번 것은 사례가 아니므로, 이슈로써 메모리를 잊어버립시다.

네트워크나 디스크 같은 다른 측정을 살펴봐야 하는데, 모든 사례에서 같은 것들이 진실이지만, 자원의 부족은 영향을 주지만, 확실하다고 말하기 어렵습니다. 부족을 발견 못한다면 모든게 괜찮다는 것을 의미하지 않습니다.

Database

이 문제의 특별히 좋은 예는 데이터베이스입니다. 매우 자주 데이터베이스는 적어도 응용프로그램쪽 사람들에 의해 모든 성능 문제의 원천으로 고려됩니다. DBA's and operations point of view로부터 데이터베이스는 자주 잘 동작합니다. 이유가 충분히 간단한데, 데이터베이스는 자원의 부족없이 동작하지 않고, 특별히 길게 동작하거나 CPU 소모 문장 또는 프로세스 동작이  없고 대부분 문장은 매우 빨리 실행됩니다. 그래서 데이터베이스는 문제가 될 수 없습니다.

Looking at the Application

사용자가 성능 문제를 보고 받으면 해야할 첫번째 일은 응답시간과 시스템안에서 분배(distribution)를 살펴봐야 합니다.

The overall distribution in our web application

시스템에서 전체적인 분배는 구체적인 병목을 보여주지 않습니다.

 

첫 보기에서 전체 시스템을 살펴볼 때 특별히 관심있는 어떤 것도 보지 못합니다. 사용자는 특정 요청(specific requests)이 가야한다고 불평하고 이들을 구체적으로 살펴봅니다:

Response time distribution of the search

특정 요청의 응답시간 분포는 백엔드에서 병목을 보여주고 많은 데이터베이스가 각기 모든 검색 요청을 호출합니다.

응답 시간의 주요한 부분이 백엔드와 데이터베이스에 놓여 있음을 봅니다. 데이터베이스가 응답시간의 중요한 부분을 차지한다는 것은 DBA가 틀렸음을 의미하지 않습니다. 각 단일한 검색이 평균 416 문장을 호출함을 확인합니다! 모든 문장이 1ms에 실행되고 데이터베이스 관점에서 충분히 빠름을 의미합니다. 문제는 응용프로그램 안과 데이터베이스 사용법에 있습니다. 이제 백엔드를 살펴봅시다.

Heap usage and GC activity on the backend

Heap 사용량과 GC 활동 차트는 많은 GC 동작을 보여주지만, 그러나 부정적인 영향은 없을까요?

 

JVM을 살펴보자 즉각 수많은  수많은 가베지 콜렉션(lot of garbage collection) (the red spikes)을 실행했음을 보는데, 여러분도 모든 모니터링 도구로 볼 수 있습니다. 이게 강력한 의심을 준다해도, 사용자에게 어떤 영향을 주는지 모릅니다. 그래서 영향을 살펴봅니다:

GC Runtime suspensions that have an impact on the search

검색에 직접 영향을 준 실행시간 의심들입니다. 고려는 해보지만 여전히 응답시간에 10% 정도입니다.

단일 트랜잭션은 garbage collection 에 의해 여러번 히트되고 수학적으로 가베지 콜렉션이 10% 정도까지 응답시간을 차지한다는 것을 밝혀냈습니다. 이게 고려해볼만하다면 지금 당장 튜닝에 많은 시간을 쓰는 것은 맞지 않습니다. 절반으로 줄인다고 해도 응답시간 5%를 줄이는 것입니다. 가베지 콜렉션 모니터링이 중요하다면, 결론을 내기 전에 영향을 분석해야 합니다.

특정한 트랜잭션이 백엔드에서 시간을 잡아먹는 곳이 어딘지 깊게 살펴봅시다. 이걸 위해 근보적인 원인을 분리시킬 수 있는 응용프로그램 중심 모니터링이 필요합니다.
Response time distribution of the search within the backend

백엔드에서 검색의 상세한 응답시간 분포는 두 주요한 문제를 보여줍니다: 너무 많은 EJB 호출과 매우 느린 doPost 메써드

 

응용프로그램에 딱 맞는 측정으로 곧바로 응답시간 문제의 근본 원인을 보았습니다. 첫번째 검색이 호출하는 WebService가 응답시간의 큰 부분을 차지합니다. 또한 호출중에 가장 큰 CPU Hotspot 입니다. 호스트가 CPU문제가 없으면, 사실 특정한 트랜잭션에서 많은 CPU를 사용하고 있습니다. 두번째 놀랍게 많은 EJB 호출은 이미 주지한바대로 많은 데이터베이스 호출을 이끌어냅니다.

작은 메모리 관련된 이슈를 식별한 것입니다: 단지 시스템 모니터링만 하고 있다면 주목할 만한 메모리 문제가 없을 수 있습니다. CPU Hotspot이 있지만, 장비는 CPU 문제가 없을 수 있는 것도 발견했습니다. 마지막으로 가장 큰 이슈는 정확하게 응용프로그램 안에 있었습니다; 너무 많은 데이터베이스와 EJB 호출, 시스템 모니터링 레벨에서 전혀 볼 수 없습니다.

결론(Conclusion)

시스템 측정은 환경을 설명기에 매우 좋은 작업이고, 설명이 끝난 후에 시스템 측정은 환경이 무엇을 의미하는 것입니다. 환경이 자원 부족이라면 응용프로그램에 부정적인 영향이 있다고 가정하지만, 확신할 수 없습니다. 명백한 부족이 아니라면, 어쨌든 응용프로그램이 부드럽게 동작하고 있다는 암시입니다. 건강하고 안정적인 환경은 건강하고 안정적이고 성능좋은 응용프로그램을 보증하지 않습니다.

시스템과 유사하게, 응용프로그램은 자세하게 모니터링되어야 하고, 응용프로그램의 건강과 안정성을 확신하기 위해 응용프로그램에 특화된 모니터링이어야 합니다. 이런 측정을 하기 위한 일반적인 규칙은 없지만, 응용프로그램에 특화된 모니터링은 응용프로그램의 건강, 안정성, 성능에 대한 설명을 가능하게 해줍니다.

Related reading:

  1. Application Performance Monitoring in production – Step by Step Guide – Measuring a distributed system // Last time I explained logical and organizational prerequisites to...
  2. Application Performance Monitoring in production – A Step-by-Step Guide – Part 1 // Setting up Application Performance Monitoring is a big task,...
  3. The Top Java Memory Problems – Part 1 // Memory and Garbage Collection problems are still the most...
  4. Application Performance and Architectural Problems You can Find in One Hour // When we get engaged with prospects that are interested...
  5. The impact of Garbage Collection on Java performance // In my last post I explained what a major...