블로그 이미지
평범하게 살고 싶은 월급쟁이 기술적인 토론 환영합니다.같이 이야기 하고 싶으시면 부담 말고 연락주세요:이메일-bwcho75골뱅이지메일 닷컴. 조대협


Archive»


 
 

Stackdriver profiler

클라우드 컴퓨팅 & NoSQL/google cloud | 2018.04.08 21:44 | Posted by 조대협


Stack driver profiler


조대협 (http://bcho.tistory.com)


얼마전에 구글 클라우드의 모니터링 솔루션인 stack driver에서 profiler 기능이 발표되었다. (https://cloud.google.com/profiler) 

우리가 일반적으로 생각하는 성능 분석을 위한 profiling 도구로, 구글 클라우드 뿐만 아니라, 여러 서버에서 동작하는 Java/node.js/Go 애플리케이션의 성능을 모니터링할 수 있다.(파이썬은 곧 지원 예정)


장점은 코드 수정없이 간단하게 에이전트만 추가함으로써 프로파일러 사용이 가능하고, 프로파일링된 결과를 stackdriver 웹 콘솔에서 바로 확인이 가능하다는 것이다.


JDB등 전통적인 프로파일러가 있기는 하지만 보통 프로파일러가 적용되면, 애플리케이션의 성능이 극단적으로 느려지기 때문에, 운영환경에 적용이 불가능한데, Stack driver profiler의 경우에는 성능 저하가 미비하여 운영환경에도 적용이 가능하다.


"Stackdriver Profiler uses statistical techniques and extremely low-impact instrumentation that runs across all production application instances to provide a complete picture of an application’s performance without slowing it down."


아래는 자바 애플리케이션을 프로파일을 하기 위해서 프로파일러 바이너리를 agentPath에 추가한 형태이다


java \ -agentpath:/opt/cprof/profiler_java_agent.so=-cprof_service=user,-cprof_service_version=1.0.0 \ -jar ./User-0.0.1-SNAPSHOT.jar


아래는 자바 애플리케이션을 프로파일을 하기 위해서 프로파일러 바이너리를 agentPath에 추가한 형태이다

애플리케이션은 http://bcho.tistory.com/1247 에서 사용한 간단한 REST API를 사용하였다.

코드를 실행해서 프로파일링 데이타를 얻고 나면 아래와 같이 구글 클라우드 콘솔에서 프로파일링 결과를 확인할 수 있다.


위의 뷰는 WALL뷰로, 전체 프로그램이 수행되는 중에, 어느 코드가 시간을 얼마나 사용했는지를 프로파일링 해준결과이다.
이 외에도 CPU 시간으로 볼 수 도 있고, 메모리 사용률등 다양한 뷰
대규모 분산 서비스나 MSA 구조에 적합하도록 프로파일 결과를 볼 수 있는 범위를 선택이 가능한데, 상단의 메뉴를 보면 프로파일링 결과를 볼 서비스와, 프로파일 타입 (CPU,WALL:메서드별 실행시간, 메모리 사용률), 그리고 서비스가 배포된 클라우드 존, 서비스 버전 등에 따라서 선택이 가능하다. 아래는 언어별로 지원하는 프로파일 타입이다. 



Profiler의 뷰는 애플리케이션 타입에 상관이 없이 순수 프로그래밍 플랫폼에만 연관된 뷰로만 보여준다.
무슨이야기인가 하면, 보통 웹 애플리케이션은 멀티 쓰레드 타입으로 동작하고, REQUEST가 들어오면 쓰레드가 하나의 요청을 처리하고 빠지는 형태이기 때문에, 쓰레드별로 어떤 메서드가 순차적으로 실행되었는지등의 뷰를 선호하는데, JENNIFER나 오픈 소스 스카우터와 같은 APM (Application Peformance Monitoring)툴이 이러한 뷰를 제공한다. 

위의 샘플을 보더라도, 톰캣서버의 쓰레드들이 대부분 모니터링 될뿐 직접 코딩한 메서드들이 관측 되지는 않는다. (사용자 코드가 적고, 실행시 별로 크게 시간을 소요하지 않는 것도 원인이기는 하지만)

만약에 REQUEST에 대한 메서드별 소요 시간 모니터링 및 병목 구간 확인을 하려면, Stack driver profiler보다는 Stack driver trace를 사용하는 것이 적절하다. http://bcho.tistory.com/1245

그래서 Stack Driver는 성능 모니터링 (APM)제품군을 Trace, Profiler, Debugger 3가지로 묶고 있고, (Debugger는 나중에 시간이 되면 테스트하고 다루도록 하겠다.) 각기 다른 뷰로 상호 보완적인 관점에서 성능 모니터링이 가능하도록 하고 있다.



Zipkin을 이용한 MSA 환경에서 분산 트렌젝션의 추적 #1

조대협 (http://bcho.tistory.com)

개념

분산 트렌젝션이랑 여러개의 서비스를 걸쳐서 이루어 지는 트렌젝션을 추적하는 기능을 정의한다.

마이크로 서비스 아키텍쳐 (이하 MSA)와 같은 구조에서는 하나의 HTTP 호출이 내부적으로 여러개의 서비스를 거쳐서 일어나게 되는데, 그러면 어느 구간에서 병목이 생기는지 추적하기가 어려워진다.

아래 그림을 보면 클라이언트가 Service A를 호출하고, Service A 가 Service B,D 를, Service B가 Service C를 호출한다.


이렇게 트렌젝션이 여러 컴포넌트의 조합을 통해서 발생하기 때문에 Jennifer와 같은 전통적인 APM (Application Performance Monitoring) 도구를 이용해서 추적하기가 어렵기 때문에 별도의 분산 로그 추적 시스템이라는 것이 필요하다.

작동 원리

그러면 이러한 분산 로그는 어떻게 수집 및 추적하는 것일까? 통상적으로 Trace와 Span 이라는 개념을 사용한다.



클라이언트가 서버로 호출한 하나의 호출을 Trace라고 했을 때, 서비스 컴포넌트간의 호출을 Span이라고 한다.각 서비스 컴포넌트들은 하나의 클라이언트 호출을 추적하기 위해서 같은 Trace Id를 사용하고, 각 서비스간의 호출은 각각 다른 Span Id를 사용한다. 이렇게 함으로써 전체 트렌젝션 시간을 Trace로 추적이 가능하고, 각 서비스별 구간 시간은 Span으로 추적할 수 있다.

솔루션

이러한 분산 로그 추적을 위한 솔루션 중에 오픈소스로는 트위터에서 개발된 ZipKin(https://zipkin.io/) , Jagger(https://jaeger.readthedocs.io/en/latest/) , Opencensus(https://opencensus.io/) 등이 있는데, 이러한 분산 로그 추적은 구글의 Dapper 논문을 기초로 디자인 되어 개발되었다.

Zipkin

그 중에서, 가장 활성화 되어 있는 오픈소스 중 하나가 Zipkin인데, 오픈 소스 생태계가 활발해서 플러그인이나 부가적인 도구들이 많다.

전체적인 구조는 다음과 같다.


<그림 . Zipkin 아키텍쳐 >


지원 프로토콜

Zipkin으로 추적할 수 있는 분산 트렌젝션은 HTTP를 기본으로 지원하고 , 이외에도 많이 사용되는 리모트 프로토콜인 gRPC를 함께 지원한다.

클라이언트 라이브러리

Zipkin 클라이언트 SDK는 https://zipkin.io/pages/existing_instrumentations 에 있는데, Zipkin에서 공식적으로 지원하는 라이브러는 아래와 같이 C#, Go, Java, Javascript,Ruby,Scala 등이 있다.




이외에도 오픈 소스 커뮤니티에서 지원하는 라이브러리로 파이썬, PHP등 대부분의 언어가 지원이 가능하다.

Zipkin 라이브러리는 수집된 트렌젝션 정보를 zipkin 서버의 collector 모듈로 전송한다. 이 때 다양한 프로토콜을 사용할 수 있는데, 일반적으로 HTTP를 사용하고, 시스템의 규모가 클 경우에는 Kafka 큐를 넣어서 Kafka 프로토콜로 전송이 가능하다.

스토리지

Zipkin 클라이언트 SDK에 의해서 전송된 정보는 스토리지에 저장된다.

사용할 수 있는 스토리지는 다음과 같다

  • In-memory

  • MySQL

  • Cassandra

  • Elastic Search

메모리는 별도의 스토리지 설치가 필요없기 때문에 간단하게 로컬에서 테스트할 수 있는 정도로 사용하는 것이 좋고, MySQL은 소규모 서비스에 적절하다. 실제로 운영환경에 적용하려면 Cassandra나 Elastic Search를 저장소로 사용하는 것이 바람직하다.

대쉬 보드

이렇게 수집된 정보는 대쉬 보드를 이용하여 시각화가 가능하다. Zipkin 서버의 대쉬보드를 사용할 수 있고, Elastic Search 백앤드를 이용한 경우에는 Kibana를 이용하여 시각화가 가능하다.


Spring Sleuth

Zipkin 라이브러리 중에서 주목해서 살펴볼 부분은 Spring / Java 지원인데, Spring에서 Sleuth라는 모듈 이름으로 공식적으로 Zipkin을 지원하기 때문에, Spring (& Springboot) 연동이 매우 쉽다.

자바 애플리케이션에서 Trace 정보와 Span 정보를 넘기는 원리는 다음과 같다.


여러개의 클래스의 메서드들을 거쳐서 트렌젝션이 완성될때, Trace 정보와 Span 정보 Context가 유지가 되어야 하는데, 자바 애플리케이션에서는 쓰레드마다 할당되는 쓰레드의 일종의 전역변수인 Thread Local 변수에 이 Trace와 Span Context 정보를 저장하여 유지한다.


분산 트렌젝션은 HTTP나 gRPC로 들어오기 때문에, Spring Sleuth는 HTTP request가 들어오는 시점과 HTTP request가 다른 서비스로 나가는 부분을 랩핑하여 Trace와 Span Context를 전달한다.

아래 그림과 같이 HTTP로 들어오는 요청의 경우에는 Servlet filter를 이용하여, Trace Id와 Span Id를 받고 (만약에 이 서비스가 맨 처음 호출되는 서비스라서 Trace Id와 Span Id가 없을 경우에는 이를 생성한다.)

, 다른 서비스로 호출을 할 경우에는 RestTemplate 을 랩핑하여, Trace Id와 Span Id와 같은 Context 정보를 실어서 보낸다.



HTTP를 이용한 Trace와 Span 정보는 HTTP Header를 통해서 전달되는데


위의 그림과 같이 x-b3로 시작하는 헤더들과 x-span-name 등을 이용하여 컨택스트를 전달한다.

이렇게 ServletFilter와 RestTemplate을 Spring 프레임웍단에서 랩핑해줌으로써, 개발자는 별도의 트레이스 코드를 넣을 필요 없이 Spring을 이용한다면 분산 트렌젝션을 추적할 수 있도록 해준다.


다음글에서는 실제로 Spring Sleuth와 Zipkin을 이용하여 분산로그를 추적하는 예제를 구현해보도록 하겠다.


Heroku에서 newrelic을 이용한 node.js 애플리케이션 모니터링 (APM)


조대협 (http://bcho.tistory.com)


Heroku에서 node.js 애플리케이션에 대한 모니터링을 살펴보자. 애플리케이션의 모니터링은 모니터링 분야에서 APM (Application Performance Monitoring)이라는 분야로, 애플리케이션에서 어떤 API 들이 호출이 되었는지, 각 로직별 응답 시간등을 추적할 수 있다. 한국에서 유명한 APM으로는 제니퍼가 있다.

Heroku에서 사용할 수 있는 APM은 여러가지가 있지만 여기서는 newrelic이라는 제품을 소개한다.

Newrelicheroku 뿐 아니라, 모니터링 시장에서 매우 유명한 제품으로 APM 기능뿐만 아니라, 서버 인프라에 대한 모니터링등 상당히 많은 기능을 제공한다.

Heroku에는 그러한 기능을 제공하지는 않고 newrelicAPM 기능만을 제공한다.

 

newrelic add-on 설치


newrelic add-on부터 설치한다. 설치 명령어는 다음과 같다.


%heroku addons:create newrelic:{상품명}


상품명은 무료 상품을 사용할 예정이기 때문에, 상품명은 ‘wayne’를 선택한다. Heroku addons 명령어를 이용해서 다음과 같이 addons를 추가 한다.



Figure 7 newrelic addon 설치

 

상품 모델은 https://elements.heroku.com/addons/newrelic#plan_selector 를 참고하면 된다.

3 dyno 모니터링에 월 49$, 300 dyno에 월 4499% 까지 다양한 상품 모델이 있다. 가격은 다른 상품에 비해서 싼편은 아니지만, APM 쪽에서 그만큼 많은 기능을 제공한다.

 

newrelic 환경 변수 설정


다음으로 추가적인 환경 설정이 필요하다. 다음과 같이 heroku config 명령어를 이용해서 다음 환경변수들을 설정한다.

 

환경변수명

설정값

설명

NEW_RELIC_APP

‘helloherokuterry’

newrelic 을 적용한 heroku 애플리케이션 이름. 여기서는  helloherokuterry 앱을 사용하기 때문에, helloherokuterry 를 사용한다

NEW_RELIC_NO_CONFIG_FILE

‘true’

newrelicnode.js에서 사용하기 위해서 원래는 newrelic.js 에 환경변수를 설정하는데, herokunewrelic에서 이 옵션을 설정하면 newrelic.js 환경에서 환경변수를 읽는데, newrelic.js를 사용하지 않고, heroku config 를 이용하여 환경 변수를 설정할 경우, 이 옵션을 ‘true’로 세팅한다.

Figure 8 newrelic 환경 변수 목록

 

다음은 heroku config 명령을 이용해서 위의 두 환경 변수를 설정한 화면이다.



Figure 9 newrelic 환경 변수 설정 화면

 

node.js 애플리케이션에 에이전트 코드 삽입


환경 변수 설정이 끝났으면, newrelic 에서 node.js 애플리케이션의 실행 정보를 수집할 수 있도록 코드를 삽입해야 한다.

에이전트는 ‘newrelic’ node.js 모듈을 설치해서 app.js 에서 로딩 하면 된다.

package.json에서 다음과 같이 newrelic 모듈에 대한 의존성을 추가한다.


{

  "name": "helloheroku",

  "version": "0.0.0",

  "private": true,

  "scripts": {

    "start": "node ./bin/www"

  },

  "dependencies": {

    "body-parser": "~1.13.2",

    "cookie-parser": "~1.3.5",

    "debug": "~2.2.0",

    "ejs": "~2.3.3",

    "express": "~4.13.1",

    "morgan": "~1.6.1",

    "serve-favicon": "~2.3.0",

    "stylus": "0.42.3",

    "newrelic" : "~1.25.5"

  }

}

Figure 10 package.json  newrelic 의존성 추가

 

다음으로 이 모듈을 애플리케이션에서 로딩해야 하는데, app.js 맨 윗줄에 아래와 같이 require(‘newrelic’) 코드를 삽입한다.

 

require('newrelic');

 

var express = require('express');

var path = require('path');

var favicon = require('serve-favicon');

Figure 11 app.jsnewrelic 에이전트 로딩 코드를 삽입

 

코드가 수정되었으면 heroku에 배포한다.

 

Newrelic을 이용한 모니터링


이제 모든 준비가 끝났다. 애플리케이션을 기동하고 heroku 대쉬보드로 들어가 보자



Figure 12 애플리케이션 선택

 

그림과 같이 대쉬보드에서 애플리케이션을 선택하면, 다음과 같이 newrelic addon이 추가된것을 확인할 수 있다.



Figure 13 newrelic APM addon이 추가된 화면

 

newrelic을 클릭해보면, 설정이 제대로 되었다면 다음과 같은 화면이 나올것이다.



Figure 14 newrelic 첫번째 접속 화면

 

상단에서 APM화면을 눌러서 APM 화면으로 들어가면 아래와 같이 애플리케이션 리스트들이 나오고, 아까 등록한 helloherokuterry 애플리케이션이 나온다.



Figure 15 newrelic에서 애플리케이션 선택

 

해당 애플리케이션을 클릭하면 다음과 같이 애플리케이션에 대한 상세 정보가 나온다.



Figure 16 newrelic APM 모니터링 화면

 

전체 응답시간(Web transation time), 초당 처리량 (Throughput), 주로 호출되는 웹 트렌젝션 목록등을 볼 수 있다.

그이에도 각 인스턴스에 대한 디테일이나 개별 트렌젝션에 대한 추적, 에러등에 대해서도 추적이 가능하다.

http://haydenjames.io/20-top-server-monitoring-application-performance-monitoring-apm-solutions/

이번에는 앞에서 설명한 Aspect J와 JMX를 이용하여 초간단 APM을 만들었습니다.
JAPM (Java Application Performance Monitor)
상용 APM 툴 설치하기 어렵거나, 간단하게 Tracing하고 싶을때 사용하시면 됩니다.
소스코드와 설치 메뉴얼등을 첨부합니다.

AOP를 이용하면 특정 클래스의 메서드 실행 전후에 Code를 삽입할 수 있다.
사용자 애플리케이션의 비지니스 메서드에 Code를 삽입하여
1. 시작 시간, 종료시간을 측정하면 비지니스 메서드의 응답 시간을 측정할 수 있고
2. JMX를 이용하여 CPU 사용시간을 측정하면 비지니스 메서드의 CPU 사용률을 측정할 수 있다.
3. Thread Local 변수를 이용하면, Transaction이 시작될때부터 끝날때 까지를 측정할 수 있다. (예를 들어 JSP는 JSPServlet : service 메서드에서부터 시작되기 때문에, AOP에서 before advice에 transaction id를 set하게 하고, after advice에서 Trace내용을 flush하게 하면 된다. 그 중간에는 Thread Local에 Trace 정보를 저장하게 한다.)

초간단하게 작성한 AspectJ를 이용한 메서드별 응답시간 측정 프로그램이다.
Aspect J 1.5이상 JVM 1.5이상에서만 동작한다.

AbstractTracerAspect.aj 소스
==
package bcho.aspectj.aspects;

import bcho.aspectj.logger.xml.*;

public abstract aspect AbstractTracerAspect {
abstract pointcut scope();
pointcut targetMethod(): scope() && execution(* *(..));
Object around(): targetMethod(){
long startTime = System.currentTimeMillis();
try{
return proceed();
}finally{
long endTime = System.currentTimeMillis();
long elapsedTime = endTime - startTime;
Logger.log(thisJoinPoint,startTime,elapsedTime);
}// try
}
}
===

Logger.java 소스

==
package bcho.aspectj.logger.xml;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
public class Logger {
static public void log(JoinPoint point,long startTime,long elapsedTime){
Signature signature;
Object args[];
signature = point.getSignature();
args = point.getArgs();
System.out.println("["+startTime+"|signature] "+signature);
System.out.println("\tElapsed time :"+elapsedTime);
for(int i=0;i<args.length;i++){
System.out.println("\targ["+i+"] :"+args[i]);
}
}
}
==

코드 작성후 ajc로 컴파일 한후에 jar로 묶고 측정할 Application이 있는 디렉토리에 배포

%TRACER_HOME%/aspectjTracer.jar
%TRACER_HOME%/META-INF/aop.xml 을 다음과 같이 작성

==
 <aspectj>
    <aspects>
       <concrete-aspect name="myTracerAspect" extends="bcho.aspectj.aspects.AbstractTracerAspect">
          <pointcut name="scope" expression="within(bcho..*) &amp;&amp; !within(bcho.aspectj..*) " />
       </concrete-aspect>
    </aspects>
</aspectj>
==

expression 부분이 Weaving을 할 class에 대한 정의 
bcho.* 시작되는 모든 클래스를 profiling하되 bcho.aspectj.* 클래스는 제거하도록 설정함. (XML이기 때문에, &를 &amp;로 정의해야 함)

다음 CLASSPATH에 다음 내용을 추가함
set CLASSPATH=%TRACER_HOME%;%CLASSPATH%
set CLASSPATH=%TRACER_HOME%/aspectjTracer.jar;%CLASSPATH%

java 실행시 다음과 같이 -Xagent 옵션 추가

java -javaagent:%ASPECTJ_HOME%/lib/aspectjweaver.jar {실행할 JAVACLASS}

를 해주면 Runtime에 Weaving이 되면서 메서드 수행 시간을 trace해준다.

자세한 내용은 다 만들면 다시 정리하겠다... ^^






Bytecode instrument with Weblogic

분류없음 | 2007.08.08 16:42 | Posted by 조대협
http://besee.sourceforge.net/extension/weblogic.html

디버깅할때 매우 유용하겠다.
TAG APM, 성능