SlideShare a Scribd company logo
1 of 53
Pinpoint
대규모분산환경추적플랫폼
강운덕
2015-04-18
2
발표자
• Backend Java developer
• 2006~
• JAVA FRAMEWORK 개발/지원
• 비동기 JAVA 네크워크 라이브러리
• JAVA 트러블 슈팅
• Heap dump, thread dump
• Open source patch, Debugging
• Multi Thread, Concurrency
• Pinpoint Technical Leader
3
발표자
4
목차
• Why
• 소개
• 기술 개요
• 어려운점
• 로드맵
5
Why
A long time ago. in a galaxy far, far away
6
Why
NOW
7
Why
• 상황
• 수십 수백대의 서버
• 많은 소프트웨어 모듈
• 복잡하게 연동된 서비스
• 문제
• 어떻게 연동되고 있는지 파악안됨
• 다른 서비스에 의해 장애가 발생
• 개별 서버에 대한 모니터링으로는 연관관계 파악이 안됨.
• 새로운 해결책이 필요
8
Why
9
Why
10
Why
11
Why
12
Why
13
Why
• 트러블 슈팅이 힘들다.
• 콘솔 들어가기 싫다
• 수십기가의 로그
• 환경, 옵션
• 수많은 종류의 라이브러리 + 다양한 버전의 라이브러리
• 야근하기 싫다
• 자신을 자동화
• 트러블슈팅시 생각하던 바, 관찰하던 뷰를 다른 사람에게도 제공
• 글로 문제를 설명하려니 어렵더라
• 잘못된 분석으로 인해 문제가 재발
14
Why
• 트러블 슈팅을 계속 하다보니 안정화되어 할일이 줄음
15
You’re Fired!!!
16
진정한 해결책
• http://www.hanbit.co.kr/events/eventview.html?event_id=freebook
17
소개
http://github.com/naver/pinpoint
• 분산트랜잭션 추적
• 애플리케이션 토폴로지 자동 발견
• 수평확장성
• 코드 수준의 가시성
• 코드를 수정하지 않고 성능정보 수집
18
소개
19
풀어야 할 문제
RPC 추적의 의미
Node1과 Node2 사이의 RPC간의
관계를 어떻게 찾을것인가?
메시지를 연관관계를 나타내는 TAG
20
TAG 동작
• Span : RPC 추적을 위한 기본 단위. RPC가 도착했을 때 처리한 작업
• Trace : 연관된 Span의 집합. Span의 집합은 TransactionId가 같음.
Trace는 SpanId와 ParaentSpanID를 통해 트리 구조로 정렬됨
• TraceId
• TrasantionId는 message id로 전체 서버군에서 unique 한 아이디
• SpanId, ParentId로 message의 관계를 정렬
21
Bytecode instrumentation
22
설치
• Java 실행시 JavaAgent 설정추가
-javaagent:$PINPOINT_PATH/pinpoint-bootstrap-$VERSION.jar
-Dpinpoint.applicationName=“$AGENT_GROUP_NAME”
-Dpinpoint.agentId =“$AGENT_UNIQUEUE_ID”
23
핵심가치
• 분산 RPC 추적
• 코드를 수정하지 않음
24
TomcatA
어플리케이션 적용 예
@Controller
public class TestController {
@RequestMapping("/test")
@ResponseBody
public String test() throws IOException {
HttpGet get = new HttpGet("http://TomcatB/hello");
HttpResponse response = httpClient.execute(get);
return EntityUtils.toString(response.getEntity());
}
}
TomcatB
@Controller
public class HelloController {
@RequestMapping("/hello")
@ResponseBody
public String hello() {
return "world!";
}
}
• Hello world! sample
25
TomcatA
@Controller
public class TestController {
@RequestMapping("/test")
@ResponseBody
public String test() throws IOException {
HttpGet get = new HttpGet("http://TomcatB/hello");
HttpResponse response = httpClient.execute(get);
return EntityUtils.toString(response.getEntity());
}
}
TomcatB
@Controller
public class HelloController {
@RequestMapping("/hello")
@ResponseBody
public String hello() {
return "world!";
}
}
어플리케이션 적용 예
26
TomcatA
@Controller
public class TestController {
@RequestMapping("/test")
@ResponseBody
public String test() throws IOException {
HttpGet get = new HttpGet("http://TomcatB/hello");
HttpResponse response = httpClient.execute(get);
return EntityUtils.toString(response.getEntity());
}
}
TomcatB
@Controller
public class HelloController {
@RequestMapping("/hello")
@ResponseBody
public String hello() {
return "world!";
}
}
어플리케이션 적용 예
27
TomcatA
@Controller
public class TestController {
@RequestMapping("/test")
@ResponseBody
public String test() throws IOException {
HttpGet get = new HttpGet("http://TomcatB/hello");
HttpResponse response = httpClient.execute(get);
return EntityUtils.toString(response.getEntity());
}
}
TomcatB
@Controller
public class HelloController {
@RequestMapping("/hello")
@ResponseBody
public String hello() {
return "world!";
}
}
어플리케이션 적용 예
28
TomcatA
@Controller
public class TestController {
@RequestMapping("/test")
@ResponseBody
public String test() throws IOException {
HttpGet get = new HttpGet("http://TomcatB/hello");
HttpResponse response = httpClient.execute(get);
return EntityUtils.toString(response.getEntity());
}
}
TomcatB
@Controller
public class HelloController {
@RequestMapping("/hello")
@ResponseBody
public String hello() {
return "world!";
}
}
어플리케이션 적용 예
29
TomcatA
@Controller
public class TestController {
@RequestMapping("/test")
@ResponseBody
public String test() throws IOException {
HttpGet get = new HttpGet("http://TomcatB/hello");
HttpResponse response = httpClient.execute(get);
return EntityUtils.toString(response.getEntity());
}
}
TomcatB
@Controller
public class HelloController {
@RequestMapping("/hello")
@ResponseBody
public String hello() {
return "world!";
}
}
어플리케이션 적용 예
30
TomcatA
@Controller
public class TestController {
@RequestMapping("/test")
@ResponseBody
public String test() throws IOException {
HttpGet get = new HttpGet("http://TomcatB/hello");
HttpResponse response = httpClient.execute(get);
return EntityUtils.toString(response.getEntity());
}
}
TomcatB
@Controller
public class HelloController {
@RequestMapping("/hello")
@ResponseBody
public String hello() {
return "world!";
}
}
어플리케이션 적용 예
31
TomcatA
@Controller
public class TestController {
@RequestMapping("/test")
@ResponseBody
public String test() throws IOException {
HttpGet get = new HttpGet("http://TomcatB/hello");
HttpResponse response = httpClient.execute(get);
return EntityUtils.toString(response.getEntity());
}
}
TomcatB
@Controller
public class HelloController {
@RequestMapping("/hello")
@ResponseBody
public String hello() {
return "world!";
}
}
• Distributed Transaction TAG
• TraceId 생성
TRANSACTION_ID : 전체 RPC 호출을 하나로 묶을수 있는 Key
SPAN_ID : 나의 ID
PARENT_SPAN_ID : 부모의 ID
내부동작
32
TomcatA
@Controller
public class TestController {
@RequestMapping("/test")
@ResponseBody
public String test() throws IOException {
HttpGet get = new HttpGet("http://TomcatB/hello");
HttpResponse response = httpClient.execute(get);
return EntityUtils.toString(response.getEntity());
}
}
TomcatB
@Controller
public class HelloController {
@RequestMapping("/hello")
@ResponseBody
public String hello() {
return "world!";
}
}
• Distributed Transaction TAG
• TraceId 생성
TRANSACTION_ID : TomcatA^시작시간^1
SPAN_ID : 10 (Random)
PARENT_SPAN_ID : -1 (ROOT)
내부동작
33
TomcatA
@Controller
public class TestController {
@RequestMapping("/test")
@ResponseBody
public String test() throws IOException {
HttpGet get = new HttpGet("http://TomcatB/hello");
HttpResponse response = httpClient.execute(get);
return EntityUtils.toString(response.getEntity());
}
}
TomcatB
@Controller
public class HelloController {
@RequestMapping("/hello")
@ResponseBody
public String hello() {
return "world!";
}
}
• Distributed Transaction TAG
• Spring Controller Method 레코딩
내부동작
34
TomcatA
@Controller
public class TestController {
@RequestMapping("/test")
@ResponseBody
public String test() throws IOException {
HttpGet get = new HttpGet("http://TomcatB/hello");
HttpResponse response = httpClient.execute(get);
return EntityUtils.toString(response.getEntity());
}
}
TomcatB
@Controller
public class HelloController {
@RequestMapping("/hello")
@ResponseBody
public String hello() {
return "world!";
}
}
• Distributed Transaction TAG
• HttpClient.execute()의 호출을 가로채서 HttpGet에 TRACE_ID를 세팅한다.
• Child TraceId 생성
TRANSACTION_ID : TomcatA^시작시간^1 -> TomcatA^시작시간^1
SPAN_ID : 10 -> 20
PARENT_SPAN_ID : -1 -> 10
• Child TraceId 를 HttpGet에 세팅
HttpGet.setHeader(PINPOINT_TRANSACTION_ID, “TomcatA^시작시간^1”)
HttpGet.setHeader(PINPOINT_SPAN_ID, “20”)
HttpGet.setHeader(PINPOINT_PARENT_SPAN_ID, “10”)
내부동작
35
TomcatA
@Controller
public class TestController {
@RequestMapping("/test")
@ResponseBody
public String test() throws IOException {
HttpGet get = new HttpGet("http://TomcatB/hello");
HttpResponse response = httpClient.execute(get);
return EntityUtils.toString(response.getEntity());
}
}
TomcatB
@Controller
public class HelloController {
@RequestMapping("/hello")
@ResponseBody
public String hello() {
return "world!";
}
}
• Distributed Transaction TAG
• TAG된 Request를 TomcatB로 전송.
Tag
Request
내부동작
36
TomcatA
@Controller
public class TestController {
@RequestMapping("/test")
@ResponseBody
public String test() throws IOException {
HttpGet get = new HttpGet("http://TomcatB/hello");
HttpResponse response = httpClient.execute(get);
return EntityUtils.toString(response.getEntity());
}
}
TomcatB
@Controller
public class HelloController {
@RequestMapping("/hello")
@ResponseBody
public String hello() {
return "world!";
}
}
• Distributed Transaction TAG
• TomcatB accept
Check Header : HttpServletRequest.getHeader(PINPOINT_TRANSACTION_ID)
• Header에서 TraceId 를 인식하여 Child로 동작
TRANSACTION_ID : TomcatA^시작시간^1
SPAN_ID : 20
PARENT_SPAN_ID : 10
Tag
Request
내부동작
37
TomcatA
@Controller
public class TestController {
@RequestMapping("/test")
@ResponseBody
public String test() throws IOException {
HttpGet get = new HttpGet("http://TomcatB/hello");
HttpResponse response = httpClient.execute(get);
return EntityUtils.toString(response.getEntity());
}
}
TomcatB
@Controller
public class HelloController {
@RequestMapping("/hello")
@ResponseBody
public String hello() {
return "world!";
}
}
• Distributed Transaction TAG
HBase
TRANSACTION_ID : TomcatA^시작시간^1
SPAN_ID : 20
PARENT_SPAN_ID : 10
Collector
RowKey
TomcatA^시작시간^1
20
10
Hello() 호출정보
TraceData
내부동작
38
TomcatA
@Controller
public class TestController {
@RequestMapping("/test")
@ResponseBody
public String test() throws IOException {
HttpGet get = new HttpGet("http://TomcatB/hello");
HttpResponse response = httpClient.execute(get);
return EntityUtils.toString(response.getEntity());
}
}
TomcatB
@Controller
public class HelloController {
@RequestMapping("/hello")
@ResponseBody
public String hello() {
return "world!";
}
}
• Distributed Transaction TAG
HBase
TRANSACTION_ID : TomcatA^시작시간^1
SPAN_ID : 10
PARENT_SPAN_ID : -1
Collector
RowKey
TomcatA^시작시간^1
20 10
10
Hello() 호출정보
-1
Test() 호출정보
TraceData
내부동작
39
RowKey
TomcatA^시작시간^1
20 10
10
Hello() 호출정보
-1
Test() 호출정보
HBase
UI
내부동작
40
트러블 슈팅
• 인프라의 각 구성요소가 정상적으로
구축이 되었는가?
• 해외Proxy에서 한국의 특정 서버로
사용자 요청의 흐름이 기대한 대로 인가?
• 응답시간이 느린 구간과 API가 있는가?
• 느린 구간에 대한 프로파일링 데이타 제공
• 성능 패턴 데이타 제공
• 개발->QA->운영단계에서의 연속적인 확인
41
어려운점
42
WARNING
• HBase도 죽고
• HBASE-7711 https://issues.apache.org/jira/browse/HBASE-7711
• Hadoop 무한루프까지
• HDFS-5225 https://issues.apache.org/jira/browse/HDFS-5225
• HBase, Hadoop 클러스터를 재시작해도 회복이 안됨
43
WARNING
44
WARNING
• 가능한 최신 버전을 Hadoop 패밀리 사용
• 관리되는 Cloudera(CDH), Hortonworks(HDP) 권장
• Pinpoint를 사용하는 사람은 Java 개발자
• 겸사겸사 HBase, Hadoop도 살펴보고, 기왕이면 소스도 까보자
• 사실 저도 다 모릅니다.
- 뭐든지 아는건 아니야. 알고 있는것만 알뿐
45
WARNING
혹시 아나요?
HBase, Hadoop, Zookeeper의 전문가가 될지
망할거 같지는 않잖아요
개인의 노력을 투자해 봅시다
46
WARNING
지금 여러분이 전문가가 될 수도 있지 않을까요?
47
WARNING
사실 그걸 노리고 선택한 Backend입니다.
48
다행인 점
• 설계 사상
• Pinpoint의 backend가 죽어도 Application은 장애가 발생하면
안된다.
• Collector
• HBase
• Hadoop
• 최우선 순위는 성능 데이터수집 X
• Application이 정상적으로 돌아가는게 최우선
49
다행인 점
• 뭐든 그렇지만 말로는 다 됨
• 큰소리 땅땅~~
“아! 걱정마시라깐요. 저를 믿으셈.
모든건 계획대로~”
50
다행인 점
51
다행인 점
• 검증되었습니다
• 직접 체험
• 한계는 분명. 버그는 커버 불가능
• 개발에서 검증 -> 운영
• 버그가 발생하면 신고해주세요. 큰 도움이 됩니다.
• 버그는 계획에 없었던 일
52
로드맵
• 알람 / Admin
• 실시간 데이터
• EndUser 모니터링
• 지원라이브러리 추가
• 개발가이드
• D2 Open Seminar (Java성능 + Pinpoint) 5월?
53
끝
감사합니다.
http://github.com/naver/pinpoint
http://helloworld.naver.com/helloworld
/1194202

More Related Content

What's hot

JBoss RHQ와 Byteman을 이용한 오픈소스 자바 애플리케이션 모니터링
JBoss RHQ와 Byteman을 이용한 오픈소스 자바 애플리케이션 모니터링JBoss RHQ와 Byteman을 이용한 오픈소스 자바 애플리케이션 모니터링
JBoss RHQ와 Byteman을 이용한 오픈소스 자바 애플리케이션 모니터링Ted Won
 
스프링군살없이세팅하기(The way to setting the Spring framework for web.)
스프링군살없이세팅하기(The way to setting the Spring framework for web.)스프링군살없이세팅하기(The way to setting the Spring framework for web.)
스프링군살없이세팅하기(The way to setting the Spring framework for web.)EunChul Shin
 
Opensource APM SCOUTER in practice
Opensource APM SCOUTER in practiceOpensource APM SCOUTER in practice
Opensource APM SCOUTER in practiceGunHee Lee
 
톰캣 #11-팁
톰캣 #11-팁톰캣 #11-팁
톰캣 #11-팁GyuSeok Lee
 
[오픈소스컨설팅]스카우터엑스 소개
[오픈소스컨설팅]스카우터엑스 소개[오픈소스컨설팅]스카우터엑스 소개
[오픈소스컨설팅]스카우터엑스 소개Open Source Consulting
 
톰캣 #10-모니터링
톰캣 #10-모니터링톰캣 #10-모니터링
톰캣 #10-모니터링GyuSeok Lee
 
[Hello world 오픈세미나]open api client개발
[Hello world 오픈세미나]open api client개발[Hello world 오픈세미나]open api client개발
[Hello world 오픈세미나]open api client개발NAVER D2
 
Tomcat 마이그레이션 도전하기 (Jins Choi)
Tomcat 마이그레이션 도전하기 (Jins Choi)Tomcat 마이그레이션 도전하기 (Jins Choi)
Tomcat 마이그레이션 도전하기 (Jins Choi)삵 (sarc.io)
 
이벤트 기반 분산 시스템을 향한 여정
이벤트 기반 분산 시스템을 향한 여정이벤트 기반 분산 시스템을 향한 여정
이벤트 기반 분산 시스템을 향한 여정Arawn Park
 
다함께, FluxUtils 한바퀴!
다함께, FluxUtils 한바퀴!다함께, FluxUtils 한바퀴!
다함께, FluxUtils 한바퀴!우영 주
 
Open source APM Scouter로 모니터링 잘 하기
Open source APM Scouter로 모니터링 잘 하기Open source APM Scouter로 모니터링 잘 하기
Open source APM Scouter로 모니터링 잘 하기GunHee Lee
 
Springcamp spring boot intro
Springcamp spring boot introSpringcamp spring boot intro
Springcamp spring boot introJae-il Lee
 
[오픈소스컨설팅]Java Performance Tuning
[오픈소스컨설팅]Java Performance Tuning[오픈소스컨설팅]Java Performance Tuning
[오픈소스컨설팅]Java Performance TuningJi-Woong Choi
 
[오픈소스컨설팅]Spring MVC
[오픈소스컨설팅]Spring MVC [오픈소스컨설팅]Spring MVC
[오픈소스컨설팅]Spring MVC Ji-Woong Choi
 
톰캣 #08-웹서버 연동
톰캣 #08-웹서버 연동톰캣 #08-웹서버 연동
톰캣 #08-웹서버 연동GyuSeok Lee
 
JSP 빠르게 시작하기
JSP 빠르게 시작하기JSP 빠르게 시작하기
JSP 빠르게 시작하기Park JoongSoo
 
톰캣 #01-소개
톰캣 #01-소개톰캣 #01-소개
톰캣 #01-소개GyuSeok Lee
 

What's hot (20)

JBoss RHQ와 Byteman을 이용한 오픈소스 자바 애플리케이션 모니터링
JBoss RHQ와 Byteman을 이용한 오픈소스 자바 애플리케이션 모니터링JBoss RHQ와 Byteman을 이용한 오픈소스 자바 애플리케이션 모니터링
JBoss RHQ와 Byteman을 이용한 오픈소스 자바 애플리케이션 모니터링
 
Spring boot actuator
Spring boot   actuatorSpring boot   actuator
Spring boot actuator
 
스프링군살없이세팅하기(The way to setting the Spring framework for web.)
스프링군살없이세팅하기(The way to setting the Spring framework for web.)스프링군살없이세팅하기(The way to setting the Spring framework for web.)
스프링군살없이세팅하기(The way to setting the Spring framework for web.)
 
Opensource APM SCOUTER in practice
Opensource APM SCOUTER in practiceOpensource APM SCOUTER in practice
Opensource APM SCOUTER in practice
 
톰캣 #11-팁
톰캣 #11-팁톰캣 #11-팁
톰캣 #11-팁
 
Html5 performance
Html5 performanceHtml5 performance
Html5 performance
 
[오픈소스컨설팅]스카우터엑스 소개
[오픈소스컨설팅]스카우터엑스 소개[오픈소스컨설팅]스카우터엑스 소개
[오픈소스컨설팅]스카우터엑스 소개
 
톰캣 #10-모니터링
톰캣 #10-모니터링톰캣 #10-모니터링
톰캣 #10-모니터링
 
[Hello world 오픈세미나]open api client개발
[Hello world 오픈세미나]open api client개발[Hello world 오픈세미나]open api client개발
[Hello world 오픈세미나]open api client개발
 
Tomcat 마이그레이션 도전하기 (Jins Choi)
Tomcat 마이그레이션 도전하기 (Jins Choi)Tomcat 마이그레이션 도전하기 (Jins Choi)
Tomcat 마이그레이션 도전하기 (Jins Choi)
 
이벤트 기반 분산 시스템을 향한 여정
이벤트 기반 분산 시스템을 향한 여정이벤트 기반 분산 시스템을 향한 여정
이벤트 기반 분산 시스템을 향한 여정
 
다함께, FluxUtils 한바퀴!
다함께, FluxUtils 한바퀴!다함께, FluxUtils 한바퀴!
다함께, FluxUtils 한바퀴!
 
Open source APM Scouter로 모니터링 잘 하기
Open source APM Scouter로 모니터링 잘 하기Open source APM Scouter로 모니터링 잘 하기
Open source APM Scouter로 모니터링 잘 하기
 
Springcamp spring boot intro
Springcamp spring boot introSpringcamp spring boot intro
Springcamp spring boot intro
 
Spring boot DI
Spring boot DISpring boot DI
Spring boot DI
 
[오픈소스컨설팅]Java Performance Tuning
[오픈소스컨설팅]Java Performance Tuning[오픈소스컨설팅]Java Performance Tuning
[오픈소스컨설팅]Java Performance Tuning
 
[오픈소스컨설팅]Spring MVC
[오픈소스컨설팅]Spring MVC [오픈소스컨설팅]Spring MVC
[오픈소스컨설팅]Spring MVC
 
톰캣 #08-웹서버 연동
톰캣 #08-웹서버 연동톰캣 #08-웹서버 연동
톰캣 #08-웹서버 연동
 
JSP 빠르게 시작하기
JSP 빠르게 시작하기JSP 빠르게 시작하기
JSP 빠르게 시작하기
 
톰캣 #01-소개
톰캣 #01-소개톰캣 #01-소개
톰캣 #01-소개
 

Viewers also liked

Springcamp 2015 - xss는 네가 맡아라
Springcamp 2015 - xss는 네가 맡아라Springcamp 2015 - xss는 네가 맡아라
Springcamp 2015 - xss는 네가 맡아라Hyeong-Kyu Lee
 
내가써본 nGrinder-SpringCamp 2015
내가써본 nGrinder-SpringCamp 2015내가써본 nGrinder-SpringCamp 2015
내가써본 nGrinder-SpringCamp 2015Lim SungHyun
 
Pinpoint 도입기 - 2016 신림프로그래머 오픈 세미나
Pinpoint 도입기 - 2016 신림프로그래머 오픈 세미나Pinpoint 도입기 - 2016 신림프로그래머 오픈 세미나
Pinpoint 도입기 - 2016 신림프로그래머 오픈 세미나none
 
SpringCamp 2014 : 미국인에게 영어 프리젠테이션을 해봤어요
SpringCamp 2014 : 미국인에게 영어 프리젠테이션을 해봤어요SpringCamp 2014 : 미국인에게 영어 프리젠테이션을 해봤어요
SpringCamp 2014 : 미국인에게 영어 프리젠테이션을 해봤어요YongSik Jeong
 
TOAST Meetup2015 - TOAST Cloud XaaS framework architecture (문지응)
TOAST Meetup2015 - TOAST Cloud XaaS framework architecture (문지응)TOAST Meetup2015 - TOAST Cloud XaaS framework architecture (문지응)
TOAST Meetup2015 - TOAST Cloud XaaS framework architecture (문지응)TOAST_NHNent
 
신림프로그래머모임_개발프로세스개선기
신림프로그래머모임_개발프로세스개선기신림프로그래머모임_개발프로세스개선기
신림프로그래머모임_개발프로세스개선기none
 
[D2 fest 2014]yobi hands on lab
[D2 fest 2014]yobi hands on lab[D2 fest 2014]yobi hands on lab
[D2 fest 2014]yobi hands on labNAVER D2
 
Spring camp 발표자료
Spring camp 발표자료Spring camp 발표자료
Spring camp 발표자료수홍 이
 
제 5회 Lisp 세미나 - 클로저 개발팀을 위한 지속적인 통합
제 5회 Lisp 세미나 - 클로저 개발팀을 위한 지속적인 통합제 5회 Lisp 세미나 - 클로저 개발팀을 위한 지속적인 통합
제 5회 Lisp 세미나 - 클로저 개발팀을 위한 지속적인 통합NAVER D2
 
제 5회 Lisp 세미나 - Graphics Programming in Clojure
제 5회 Lisp 세미나 - Graphics Programming in Clojure제 5회 Lisp 세미나 - Graphics Programming in Clojure
제 5회 Lisp 세미나 - Graphics Programming in ClojureNAVER D2
 
스프링 어플리케이션의 문제해결사례와 안티패턴
스프링 어플리케이션의 문제해결사례와 안티패턴스프링 어플리케이션의 문제해결사례와 안티패턴
스프링 어플리케이션의 문제해결사례와 안티패턴Sanghyuk Jung
 
core.logic (Clojure)
core.logic (Clojure)core.logic (Clojure)
core.logic (Clojure)Seonho Kim
 
[D2 COMMUNITY] Open Container Seoul Meetup - Docker security
[D2 COMMUNITY] Open Container Seoul Meetup - Docker security[D2 COMMUNITY] Open Container Seoul Meetup - Docker security
[D2 COMMUNITY] Open Container Seoul Meetup - Docker securityNAVER D2
 
[D2 CAMPUS] 2016 한양대학교 프로그래밍 경시대회 문제
[D2 CAMPUS] 2016 한양대학교 프로그래밍 경시대회 문제[D2 CAMPUS] 2016 한양대학교 프로그래밍 경시대회 문제
[D2 CAMPUS] 2016 한양대학교 프로그래밍 경시대회 문제NAVER D2
 
W3C Automotive 표준 개발 현황
W3C Automotive 표준 개발 현황W3C Automotive 표준 개발 현황
W3C Automotive 표준 개발 현황Wonsuk Lee
 
[D2 CAMPUS] 숭실대 SCCC 프로그래밍 경시대회 문제
[D2 CAMPUS] 숭실대 SCCC 프로그래밍 경시대회 문제[D2 CAMPUS] 숭실대 SCCC 프로그래밍 경시대회 문제
[D2 CAMPUS] 숭실대 SCCC 프로그래밍 경시대회 문제NAVER D2
 
[하코사세미나]미리보는 대규모 자바스크립트 어플리케이션 개발
[하코사세미나]미리보는 대규모 자바스크립트 어플리케이션 개발[하코사세미나]미리보는 대규모 자바스크립트 어플리케이션 개발
[하코사세미나]미리보는 대규모 자바스크립트 어플리케이션 개발정석 양
 
[D2 CAMPUS] 부산대 Alcall 프로그래밍 경시대회 문제
[D2 CAMPUS] 부산대 Alcall 프로그래밍 경시대회 문제[D2 CAMPUS] 부산대 Alcall 프로그래밍 경시대회 문제
[D2 CAMPUS] 부산대 Alcall 프로그래밍 경시대회 문제NAVER D2
 

Viewers also liked (20)

Springcamp 2015 - xss는 네가 맡아라
Springcamp 2015 - xss는 네가 맡아라Springcamp 2015 - xss는 네가 맡아라
Springcamp 2015 - xss는 네가 맡아라
 
내가써본 nGrinder-SpringCamp 2015
내가써본 nGrinder-SpringCamp 2015내가써본 nGrinder-SpringCamp 2015
내가써본 nGrinder-SpringCamp 2015
 
REST
RESTREST
REST
 
Pinpoint 도입기 - 2016 신림프로그래머 오픈 세미나
Pinpoint 도입기 - 2016 신림프로그래머 오픈 세미나Pinpoint 도입기 - 2016 신림프로그래머 오픈 세미나
Pinpoint 도입기 - 2016 신림프로그래머 오픈 세미나
 
SpringCamp 2014 : 미국인에게 영어 프리젠테이션을 해봤어요
SpringCamp 2014 : 미국인에게 영어 프리젠테이션을 해봤어요SpringCamp 2014 : 미국인에게 영어 프리젠테이션을 해봤어요
SpringCamp 2014 : 미국인에게 영어 프리젠테이션을 해봤어요
 
TOAST Meetup2015 - TOAST Cloud XaaS framework architecture (문지응)
TOAST Meetup2015 - TOAST Cloud XaaS framework architecture (문지응)TOAST Meetup2015 - TOAST Cloud XaaS framework architecture (문지응)
TOAST Meetup2015 - TOAST Cloud XaaS framework architecture (문지응)
 
신림프로그래머모임_개발프로세스개선기
신림프로그래머모임_개발프로세스개선기신림프로그래머모임_개발프로세스개선기
신림프로그래머모임_개발프로세스개선기
 
[D2 fest 2014]yobi hands on lab
[D2 fest 2014]yobi hands on lab[D2 fest 2014]yobi hands on lab
[D2 fest 2014]yobi hands on lab
 
Spring camp 발표자료
Spring camp 발표자료Spring camp 발표자료
Spring camp 발표자료
 
Re frame
Re frameRe frame
Re frame
 
제 5회 Lisp 세미나 - 클로저 개발팀을 위한 지속적인 통합
제 5회 Lisp 세미나 - 클로저 개발팀을 위한 지속적인 통합제 5회 Lisp 세미나 - 클로저 개발팀을 위한 지속적인 통합
제 5회 Lisp 세미나 - 클로저 개발팀을 위한 지속적인 통합
 
제 5회 Lisp 세미나 - Graphics Programming in Clojure
제 5회 Lisp 세미나 - Graphics Programming in Clojure제 5회 Lisp 세미나 - Graphics Programming in Clojure
제 5회 Lisp 세미나 - Graphics Programming in Clojure
 
스프링 어플리케이션의 문제해결사례와 안티패턴
스프링 어플리케이션의 문제해결사례와 안티패턴스프링 어플리케이션의 문제해결사례와 안티패턴
스프링 어플리케이션의 문제해결사례와 안티패턴
 
core.logic (Clojure)
core.logic (Clojure)core.logic (Clojure)
core.logic (Clojure)
 
[D2 COMMUNITY] Open Container Seoul Meetup - Docker security
[D2 COMMUNITY] Open Container Seoul Meetup - Docker security[D2 COMMUNITY] Open Container Seoul Meetup - Docker security
[D2 COMMUNITY] Open Container Seoul Meetup - Docker security
 
[D2 CAMPUS] 2016 한양대학교 프로그래밍 경시대회 문제
[D2 CAMPUS] 2016 한양대학교 프로그래밍 경시대회 문제[D2 CAMPUS] 2016 한양대학교 프로그래밍 경시대회 문제
[D2 CAMPUS] 2016 한양대학교 프로그래밍 경시대회 문제
 
W3C Automotive 표준 개발 현황
W3C Automotive 표준 개발 현황W3C Automotive 표준 개발 현황
W3C Automotive 표준 개발 현황
 
[D2 CAMPUS] 숭실대 SCCC 프로그래밍 경시대회 문제
[D2 CAMPUS] 숭실대 SCCC 프로그래밍 경시대회 문제[D2 CAMPUS] 숭실대 SCCC 프로그래밍 경시대회 문제
[D2 CAMPUS] 숭실대 SCCC 프로그래밍 경시대회 문제
 
[하코사세미나]미리보는 대규모 자바스크립트 어플리케이션 개발
[하코사세미나]미리보는 대규모 자바스크립트 어플리케이션 개발[하코사세미나]미리보는 대규모 자바스크립트 어플리케이션 개발
[하코사세미나]미리보는 대규모 자바스크립트 어플리케이션 개발
 
[D2 CAMPUS] 부산대 Alcall 프로그래밍 경시대회 문제
[D2 CAMPUS] 부산대 Alcall 프로그래밍 경시대회 문제[D2 CAMPUS] 부산대 Alcall 프로그래밍 경시대회 문제
[D2 CAMPUS] 부산대 Alcall 프로그래밍 경시대회 문제
 

Similar to Pinpoint spring_camp 2015

Spring boot 공작소(1-4장)
Spring boot 공작소(1-4장)Spring boot 공작소(1-4장)
Spring boot 공작소(1-4장)Choonghyun Yang
 
Catalyst Framework 살펴보기
Catalyst Framework 살펴보기Catalyst Framework 살펴보기
Catalyst Framework 살펴보기corund
 
Jdk(java) 7 - 5. invoke-dynamic
Jdk(java) 7 - 5. invoke-dynamicJdk(java) 7 - 5. invoke-dynamic
Jdk(java) 7 - 5. invoke-dynamicknight1128
 
Spring test mvc 발표자료
Spring test mvc 발표자료Spring test mvc 발표자료
Spring test mvc 발표자료수홍 이
 
Java Virtual Machine, Call stack, Java Byte Code
Java Virtual Machine, Call stack, Java Byte CodeJava Virtual Machine, Call stack, Java Byte Code
Java Virtual Machine, Call stack, Java Byte CodeJavajigi Jaesung
 
Java 8 & Beyond
Java 8 & BeyondJava 8 & Beyond
Java 8 & BeyondJay Lee
 
.NET에서 비동기 프로그래밍 배우기
.NET에서 비동기 프로그래밍 배우기.NET에서 비동기 프로그래밍 배우기
.NET에서 비동기 프로그래밍 배우기Seong Won Mun
 
GKAC 2015 Apr. - Battery, 안드로이드를 위한 쉬운 웹 API 호출
GKAC 2015 Apr. - Battery, 안드로이드를 위한 쉬운 웹 API 호출GKAC 2015 Apr. - Battery, 안드로이드를 위한 쉬운 웹 API 호출
GKAC 2015 Apr. - Battery, 안드로이드를 위한 쉬운 웹 API 호출GDG Korea
 
vert.x 를 활용한 분산서버 개발하기
vert.x 를 활용한 분산서버 개발하기vert.x 를 활용한 분산서버 개발하기
vert.x 를 활용한 분산서버 개발하기John Kim
 
[D2 오픈세미나]5.robolectric 안드로이드 테스팅
[D2 오픈세미나]5.robolectric 안드로이드 테스팅[D2 오픈세미나]5.robolectric 안드로이드 테스팅
[D2 오픈세미나]5.robolectric 안드로이드 테스팅NAVER D2
 
Meteor React Tutorial 따라하기
Meteor React Tutorial 따라하기Meteor React Tutorial 따라하기
Meteor React Tutorial 따라하기Jiam Seo
 
Scala, Spring-Boot, JPA의 불편하면서도 즐거운 동거
Scala, Spring-Boot, JPA의 불편하면서도 즐거운 동거Scala, Spring-Boot, JPA의 불편하면서도 즐거운 동거
Scala, Spring-Boot, JPA의 불편하면서도 즐거운 동거Javajigi Jaesung
 
[웹기반시스템 3조]e govframe 중간고사 제출 정리
[웹기반시스템 3조]e govframe 중간고사 제출 정리[웹기반시스템 3조]e govframe 중간고사 제출 정리
[웹기반시스템 3조]e govframe 중간고사 제출 정리구 봉
 
Node.js 시작하기
Node.js 시작하기Node.js 시작하기
Node.js 시작하기Huey Park
 

Similar to Pinpoint spring_camp 2015 (20)

Spring boot 공작소(1-4장)
Spring boot 공작소(1-4장)Spring boot 공작소(1-4장)
Spring boot 공작소(1-4장)
 
Catalyst Framework 살펴보기
Catalyst Framework 살펴보기Catalyst Framework 살펴보기
Catalyst Framework 살펴보기
 
Jdk(java) 7 - 5. invoke-dynamic
Jdk(java) 7 - 5. invoke-dynamicJdk(java) 7 - 5. invoke-dynamic
Jdk(java) 7 - 5. invoke-dynamic
 
Spring test mvc 발표자료
Spring test mvc 발표자료Spring test mvc 발표자료
Spring test mvc 발표자료
 
Java Virtual Machine, Call stack, Java Byte Code
Java Virtual Machine, Call stack, Java Byte CodeJava Virtual Machine, Call stack, Java Byte Code
Java Virtual Machine, Call stack, Java Byte Code
 
Java 8 & Beyond
Java 8 & BeyondJava 8 & Beyond
Java 8 & Beyond
 
.NET에서 비동기 프로그래밍 배우기
.NET에서 비동기 프로그래밍 배우기.NET에서 비동기 프로그래밍 배우기
.NET에서 비동기 프로그래밍 배우기
 
GKAC 2015 Apr. - Battery, 안드로이드를 위한 쉬운 웹 API 호출
GKAC 2015 Apr. - Battery, 안드로이드를 위한 쉬운 웹 API 호출GKAC 2015 Apr. - Battery, 안드로이드를 위한 쉬운 웹 API 호출
GKAC 2015 Apr. - Battery, 안드로이드를 위한 쉬운 웹 API 호출
 
Springmvc
SpringmvcSpringmvc
Springmvc
 
4-2. ajax
4-2. ajax4-2. ajax
4-2. ajax
 
Clean code appendix 1
Clean code appendix 1Clean code appendix 1
Clean code appendix 1
 
vert.x 를 활용한 분산서버 개발하기
vert.x 를 활용한 분산서버 개발하기vert.x 를 활용한 분산서버 개발하기
vert.x 를 활용한 분산서버 개발하기
 
HTTP web server 구현
HTTP web server 구현HTTP web server 구현
HTTP web server 구현
 
[D2 오픈세미나]5.robolectric 안드로이드 테스팅
[D2 오픈세미나]5.robolectric 안드로이드 테스팅[D2 오픈세미나]5.robolectric 안드로이드 테스팅
[D2 오픈세미나]5.robolectric 안드로이드 테스팅
 
4-3. jquery
4-3. jquery4-3. jquery
4-3. jquery
 
Meteor React Tutorial 따라하기
Meteor React Tutorial 따라하기Meteor React Tutorial 따라하기
Meteor React Tutorial 따라하기
 
Scala, Spring-Boot, JPA의 불편하면서도 즐거운 동거
Scala, Spring-Boot, JPA의 불편하면서도 즐거운 동거Scala, Spring-Boot, JPA의 불편하면서도 즐거운 동거
Scala, Spring-Boot, JPA의 불편하면서도 즐거운 동거
 
Rx java essentials
Rx java essentialsRx java essentials
Rx java essentials
 
[웹기반시스템 3조]e govframe 중간고사 제출 정리
[웹기반시스템 3조]e govframe 중간고사 제출 정리[웹기반시스템 3조]e govframe 중간고사 제출 정리
[웹기반시스템 3조]e govframe 중간고사 제출 정리
 
Node.js 시작하기
Node.js 시작하기Node.js 시작하기
Node.js 시작하기
 

Pinpoint spring_camp 2015

  • 2. 2 발표자 • Backend Java developer • 2006~ • JAVA FRAMEWORK 개발/지원 • 비동기 JAVA 네크워크 라이브러리 • JAVA 트러블 슈팅 • Heap dump, thread dump • Open source patch, Debugging • Multi Thread, Concurrency • Pinpoint Technical Leader
  • 4. 4 목차 • Why • 소개 • 기술 개요 • 어려운점 • 로드맵
  • 5. 5 Why A long time ago. in a galaxy far, far away
  • 7. 7 Why • 상황 • 수십 수백대의 서버 • 많은 소프트웨어 모듈 • 복잡하게 연동된 서비스 • 문제 • 어떻게 연동되고 있는지 파악안됨 • 다른 서비스에 의해 장애가 발생 • 개별 서버에 대한 모니터링으로는 연관관계 파악이 안됨. • 새로운 해결책이 필요
  • 13. 13 Why • 트러블 슈팅이 힘들다. • 콘솔 들어가기 싫다 • 수십기가의 로그 • 환경, 옵션 • 수많은 종류의 라이브러리 + 다양한 버전의 라이브러리 • 야근하기 싫다 • 자신을 자동화 • 트러블슈팅시 생각하던 바, 관찰하던 뷰를 다른 사람에게도 제공 • 글로 문제를 설명하려니 어렵더라 • 잘못된 분석으로 인해 문제가 재발
  • 14. 14 Why • 트러블 슈팅을 계속 하다보니 안정화되어 할일이 줄음
  • 17. 17 소개 http://github.com/naver/pinpoint • 분산트랜잭션 추적 • 애플리케이션 토폴로지 자동 발견 • 수평확장성 • 코드 수준의 가시성 • 코드를 수정하지 않고 성능정보 수집
  • 19. 19 풀어야 할 문제 RPC 추적의 의미 Node1과 Node2 사이의 RPC간의 관계를 어떻게 찾을것인가? 메시지를 연관관계를 나타내는 TAG
  • 20. 20 TAG 동작 • Span : RPC 추적을 위한 기본 단위. RPC가 도착했을 때 처리한 작업 • Trace : 연관된 Span의 집합. Span의 집합은 TransactionId가 같음. Trace는 SpanId와 ParaentSpanID를 통해 트리 구조로 정렬됨 • TraceId • TrasantionId는 message id로 전체 서버군에서 unique 한 아이디 • SpanId, ParentId로 message의 관계를 정렬
  • 22. 22 설치 • Java 실행시 JavaAgent 설정추가 -javaagent:$PINPOINT_PATH/pinpoint-bootstrap-$VERSION.jar -Dpinpoint.applicationName=“$AGENT_GROUP_NAME” -Dpinpoint.agentId =“$AGENT_UNIQUEUE_ID”
  • 23. 23 핵심가치 • 분산 RPC 추적 • 코드를 수정하지 않음
  • 24. 24 TomcatA 어플리케이션 적용 예 @Controller public class TestController { @RequestMapping("/test") @ResponseBody public String test() throws IOException { HttpGet get = new HttpGet("http://TomcatB/hello"); HttpResponse response = httpClient.execute(get); return EntityUtils.toString(response.getEntity()); } } TomcatB @Controller public class HelloController { @RequestMapping("/hello") @ResponseBody public String hello() { return "world!"; } } • Hello world! sample
  • 25. 25 TomcatA @Controller public class TestController { @RequestMapping("/test") @ResponseBody public String test() throws IOException { HttpGet get = new HttpGet("http://TomcatB/hello"); HttpResponse response = httpClient.execute(get); return EntityUtils.toString(response.getEntity()); } } TomcatB @Controller public class HelloController { @RequestMapping("/hello") @ResponseBody public String hello() { return "world!"; } } 어플리케이션 적용 예
  • 26. 26 TomcatA @Controller public class TestController { @RequestMapping("/test") @ResponseBody public String test() throws IOException { HttpGet get = new HttpGet("http://TomcatB/hello"); HttpResponse response = httpClient.execute(get); return EntityUtils.toString(response.getEntity()); } } TomcatB @Controller public class HelloController { @RequestMapping("/hello") @ResponseBody public String hello() { return "world!"; } } 어플리케이션 적용 예
  • 27. 27 TomcatA @Controller public class TestController { @RequestMapping("/test") @ResponseBody public String test() throws IOException { HttpGet get = new HttpGet("http://TomcatB/hello"); HttpResponse response = httpClient.execute(get); return EntityUtils.toString(response.getEntity()); } } TomcatB @Controller public class HelloController { @RequestMapping("/hello") @ResponseBody public String hello() { return "world!"; } } 어플리케이션 적용 예
  • 28. 28 TomcatA @Controller public class TestController { @RequestMapping("/test") @ResponseBody public String test() throws IOException { HttpGet get = new HttpGet("http://TomcatB/hello"); HttpResponse response = httpClient.execute(get); return EntityUtils.toString(response.getEntity()); } } TomcatB @Controller public class HelloController { @RequestMapping("/hello") @ResponseBody public String hello() { return "world!"; } } 어플리케이션 적용 예
  • 29. 29 TomcatA @Controller public class TestController { @RequestMapping("/test") @ResponseBody public String test() throws IOException { HttpGet get = new HttpGet("http://TomcatB/hello"); HttpResponse response = httpClient.execute(get); return EntityUtils.toString(response.getEntity()); } } TomcatB @Controller public class HelloController { @RequestMapping("/hello") @ResponseBody public String hello() { return "world!"; } } 어플리케이션 적용 예
  • 30. 30 TomcatA @Controller public class TestController { @RequestMapping("/test") @ResponseBody public String test() throws IOException { HttpGet get = new HttpGet("http://TomcatB/hello"); HttpResponse response = httpClient.execute(get); return EntityUtils.toString(response.getEntity()); } } TomcatB @Controller public class HelloController { @RequestMapping("/hello") @ResponseBody public String hello() { return "world!"; } } 어플리케이션 적용 예
  • 31. 31 TomcatA @Controller public class TestController { @RequestMapping("/test") @ResponseBody public String test() throws IOException { HttpGet get = new HttpGet("http://TomcatB/hello"); HttpResponse response = httpClient.execute(get); return EntityUtils.toString(response.getEntity()); } } TomcatB @Controller public class HelloController { @RequestMapping("/hello") @ResponseBody public String hello() { return "world!"; } } • Distributed Transaction TAG • TraceId 생성 TRANSACTION_ID : 전체 RPC 호출을 하나로 묶을수 있는 Key SPAN_ID : 나의 ID PARENT_SPAN_ID : 부모의 ID 내부동작
  • 32. 32 TomcatA @Controller public class TestController { @RequestMapping("/test") @ResponseBody public String test() throws IOException { HttpGet get = new HttpGet("http://TomcatB/hello"); HttpResponse response = httpClient.execute(get); return EntityUtils.toString(response.getEntity()); } } TomcatB @Controller public class HelloController { @RequestMapping("/hello") @ResponseBody public String hello() { return "world!"; } } • Distributed Transaction TAG • TraceId 생성 TRANSACTION_ID : TomcatA^시작시간^1 SPAN_ID : 10 (Random) PARENT_SPAN_ID : -1 (ROOT) 내부동작
  • 33. 33 TomcatA @Controller public class TestController { @RequestMapping("/test") @ResponseBody public String test() throws IOException { HttpGet get = new HttpGet("http://TomcatB/hello"); HttpResponse response = httpClient.execute(get); return EntityUtils.toString(response.getEntity()); } } TomcatB @Controller public class HelloController { @RequestMapping("/hello") @ResponseBody public String hello() { return "world!"; } } • Distributed Transaction TAG • Spring Controller Method 레코딩 내부동작
  • 34. 34 TomcatA @Controller public class TestController { @RequestMapping("/test") @ResponseBody public String test() throws IOException { HttpGet get = new HttpGet("http://TomcatB/hello"); HttpResponse response = httpClient.execute(get); return EntityUtils.toString(response.getEntity()); } } TomcatB @Controller public class HelloController { @RequestMapping("/hello") @ResponseBody public String hello() { return "world!"; } } • Distributed Transaction TAG • HttpClient.execute()의 호출을 가로채서 HttpGet에 TRACE_ID를 세팅한다. • Child TraceId 생성 TRANSACTION_ID : TomcatA^시작시간^1 -> TomcatA^시작시간^1 SPAN_ID : 10 -> 20 PARENT_SPAN_ID : -1 -> 10 • Child TraceId 를 HttpGet에 세팅 HttpGet.setHeader(PINPOINT_TRANSACTION_ID, “TomcatA^시작시간^1”) HttpGet.setHeader(PINPOINT_SPAN_ID, “20”) HttpGet.setHeader(PINPOINT_PARENT_SPAN_ID, “10”) 내부동작
  • 35. 35 TomcatA @Controller public class TestController { @RequestMapping("/test") @ResponseBody public String test() throws IOException { HttpGet get = new HttpGet("http://TomcatB/hello"); HttpResponse response = httpClient.execute(get); return EntityUtils.toString(response.getEntity()); } } TomcatB @Controller public class HelloController { @RequestMapping("/hello") @ResponseBody public String hello() { return "world!"; } } • Distributed Transaction TAG • TAG된 Request를 TomcatB로 전송. Tag Request 내부동작
  • 36. 36 TomcatA @Controller public class TestController { @RequestMapping("/test") @ResponseBody public String test() throws IOException { HttpGet get = new HttpGet("http://TomcatB/hello"); HttpResponse response = httpClient.execute(get); return EntityUtils.toString(response.getEntity()); } } TomcatB @Controller public class HelloController { @RequestMapping("/hello") @ResponseBody public String hello() { return "world!"; } } • Distributed Transaction TAG • TomcatB accept Check Header : HttpServletRequest.getHeader(PINPOINT_TRANSACTION_ID) • Header에서 TraceId 를 인식하여 Child로 동작 TRANSACTION_ID : TomcatA^시작시간^1 SPAN_ID : 20 PARENT_SPAN_ID : 10 Tag Request 내부동작
  • 37. 37 TomcatA @Controller public class TestController { @RequestMapping("/test") @ResponseBody public String test() throws IOException { HttpGet get = new HttpGet("http://TomcatB/hello"); HttpResponse response = httpClient.execute(get); return EntityUtils.toString(response.getEntity()); } } TomcatB @Controller public class HelloController { @RequestMapping("/hello") @ResponseBody public String hello() { return "world!"; } } • Distributed Transaction TAG HBase TRANSACTION_ID : TomcatA^시작시간^1 SPAN_ID : 20 PARENT_SPAN_ID : 10 Collector RowKey TomcatA^시작시간^1 20 10 Hello() 호출정보 TraceData 내부동작
  • 38. 38 TomcatA @Controller public class TestController { @RequestMapping("/test") @ResponseBody public String test() throws IOException { HttpGet get = new HttpGet("http://TomcatB/hello"); HttpResponse response = httpClient.execute(get); return EntityUtils.toString(response.getEntity()); } } TomcatB @Controller public class HelloController { @RequestMapping("/hello") @ResponseBody public String hello() { return "world!"; } } • Distributed Transaction TAG HBase TRANSACTION_ID : TomcatA^시작시간^1 SPAN_ID : 10 PARENT_SPAN_ID : -1 Collector RowKey TomcatA^시작시간^1 20 10 10 Hello() 호출정보 -1 Test() 호출정보 TraceData 내부동작
  • 40. 40 트러블 슈팅 • 인프라의 각 구성요소가 정상적으로 구축이 되었는가? • 해외Proxy에서 한국의 특정 서버로 사용자 요청의 흐름이 기대한 대로 인가? • 응답시간이 느린 구간과 API가 있는가? • 느린 구간에 대한 프로파일링 데이타 제공 • 성능 패턴 데이타 제공 • 개발->QA->운영단계에서의 연속적인 확인
  • 42. 42 WARNING • HBase도 죽고 • HBASE-7711 https://issues.apache.org/jira/browse/HBASE-7711 • Hadoop 무한루프까지 • HDFS-5225 https://issues.apache.org/jira/browse/HDFS-5225 • HBase, Hadoop 클러스터를 재시작해도 회복이 안됨
  • 44. 44 WARNING • 가능한 최신 버전을 Hadoop 패밀리 사용 • 관리되는 Cloudera(CDH), Hortonworks(HDP) 권장 • Pinpoint를 사용하는 사람은 Java 개발자 • 겸사겸사 HBase, Hadoop도 살펴보고, 기왕이면 소스도 까보자 • 사실 저도 다 모릅니다. - 뭐든지 아는건 아니야. 알고 있는것만 알뿐
  • 45. 45 WARNING 혹시 아나요? HBase, Hadoop, Zookeeper의 전문가가 될지 망할거 같지는 않잖아요 개인의 노력을 투자해 봅시다
  • 46. 46 WARNING 지금 여러분이 전문가가 될 수도 있지 않을까요?
  • 47. 47 WARNING 사실 그걸 노리고 선택한 Backend입니다.
  • 48. 48 다행인 점 • 설계 사상 • Pinpoint의 backend가 죽어도 Application은 장애가 발생하면 안된다. • Collector • HBase • Hadoop • 최우선 순위는 성능 데이터수집 X • Application이 정상적으로 돌아가는게 최우선
  • 49. 49 다행인 점 • 뭐든 그렇지만 말로는 다 됨 • 큰소리 땅땅~~ “아! 걱정마시라깐요. 저를 믿으셈. 모든건 계획대로~”
  • 51. 51 다행인 점 • 검증되었습니다 • 직접 체험 • 한계는 분명. 버그는 커버 불가능 • 개발에서 검증 -> 운영 • 버그가 발생하면 신고해주세요. 큰 도움이 됩니다. • 버그는 계획에 없었던 일
  • 52. 52 로드맵 • 알람 / Admin • 실시간 데이터 • EndUser 모니터링 • 지원라이브러리 추가 • 개발가이드 • D2 Open Seminar (Java성능 + Pinpoint) 5월?

Editor's Notes

  1. Backend java developer 입니다. Java 기반의 네크워크 라이브러리, 프레임워크, 트러블슈팅을 지원했고, 현재는 pinpiont의 TL을 하고 있구. pinpoint를 직접개발했습니다.
  2. 이 책의 저자이기도 합니다.
  3. 과거에는 사용자가 얼마 안되고, 서버도 얼마 안됬습니다. 서버의 대수도 작았고, 단순했습니다.
  4. 현재는 사용자가 많아지고, 서비스가 점점 복잡해지면서, 복잡도가 증가하였습니다. 옆 화면은 netflix의 서버모습인데. 굉장히 복잡한것을 볼수 있습니다.
  5. 상황을 살펴 보면 시스템이 점점 복잡해 지면서 문제가 발생하고 있는것을 볼수 있는데. 더 이상은 기존의 방식. 즉 로그를 살펴 다던가? 개별 시스템을 살펴본다든가 하는것으로는 시스템의 복잡도를 커버하기 힘들어지고 있다는 것을 느낄수 있습니다. 즉 이 상황을 개선할수 있는 새로운 무엇이 필요하다는 생각을 할수 있습니다.
  6. 구글은 이미 이 문제를 해결하기 위해서 dapper란것을 2010년에 발표 했습니다. 아쉽게 비공개입니다.
  7. Twitter는 dapper를 기반으로 zipkin이라는 플랫폼을 개발했습니다.
  8. 여러가지 상용 솔류션들도 있습니다. 한국에서 가장 유명한 제니퍼도 있구요. 세계에서 가장 좋다고 하는 3개의 제품군도 있습니다.
  9. 네이버도 이문제를 해결하기위해서 Pinpoint를 개발했습니다.
  10. 네이버의 시스템도 정말 복잡하거든요. 우리 시스템의 보잡도를 모르고 있다가, Pinpoint를 통해서 우리가 이렇게 복잡했나를 발견하기도 합니다.
  11. 개인적으로 필요했습니다. 트러블슈팅을 담당했지만. 시스템이 복잡하니 트러블슈팅이 점점 힘들어졌습니다. 알아야 될것도 많구요. 일일이 서버 콘솔들어가기도 싫고, 수십기가 로그 볼려니 눈도 아프고 힘들고, 개별 라이브러리를 다 살펴보려니 피곤하더라구요 그리고 트러블슈팅하느라 야근하기도 싫구요. 또 하나는 여러 조직에서 트러블슈팅하고 계신데, 이걸 좀더 편하게 지원을 하고 싶었습니다. 구지 제가 메일을 쓰고 분석을 하지 않더라도, 제가 보고 있는 좀더 편하게 제공하고 싶었습니다.
  12. 앞에는꺼는 아무래도 좀 좋은 동기고, 살작 애매한 동기는 트러블슈팅도 계속하다 보니. 시스템이 안정화되서 할일이 없어지더라구요. 최초 시작할때는 거의 1년 내내 장애지원을 했는데. 해가 갈수록 빈도가 줄거나, 기존에 해결한 방안을 대입하면 되는거라. 시간이 줄었습니다. 아무튼 할일이 전반적으로 줄었습니다. 그런데 할일이 줄면 어떻게 될까요?
  13. 뭐긴 뭐가요. 해고죠.
  14. 진정한 해결책입니다. 더군다나 공짜 유지보수가 어렵게 짜면 평생 개발자로 먹고살수 있습니다. ㅎㅎ. 이건농담인거 아시죠. 아무튼 이건 나쁜방향으로의 해결이죠. 이렇게 하면 회사도 망하고 자신의 발전도 없어집니다. 좋은 방향의 해결책으로 이런 문제를 타계할수 있는 pinpint를 개발하게 되었습니다.
  15. Pinpoint의 github 내용인데. 간단하게 설명하면 Pinpoint는 APM툴이고, java의 성능 모니터링을 하는 플랫폼입니다. 시스템 모니터링 툴과는 다르게, APM툴은 걷을 보는게 아니고, 실제 어플리케이션의 수행하는 정보를 프로파일 할수 있는 툴입니다. 시스템 모니터링이 사진기라면, APM툴은 X-ray 처럼 내부를 볼수 있는 툴입니다. 말로 들으면 어려우실거니. 직접 화면을 보도록 하겠습니다.
  16. 화면을 보면 단순한데, 이와 같이 어플리케이션이 어떻게 동작하는 비주얼 하게 볼수 있습니다.
  17. 핀포인트가 해결한 문제를 보겠습니다 중요한 RPC 추적에 대한 내용인데요. 핵심의 메시지의 관계를 어떻게 짝것인가에 대한 문제입니다. 이문제를 해결하기 위해서 핀포인트는 메시지에 추적을 위한 tag를 달고 있습니다.
  18. 추적태그 는 해당 그림과 같이 동작합니다. 중요한 추적키는 transaction id 전체 를 관통하는 유니크 아이디가 존재하구요. 이 키를 기반으로 부모 자식관계를 정렬할수 있는 spanId와 parentSpan가 존재합니다. 이 추적키를 기반으로 RPC메시지를 추적합니다.
  19. 그리고 이 추적 태그에 처리는 bytecode instrumentation을 기반으로 자동으로 핀포인에서 처리합니다. 원리는 간단한게. 추적할 메소드를 대상으로 추적 코드를 앞뒤로 심는것으로 이해하면 됩니다.
  20. 그리고 이 추적 태그에 처리는 bytecode instrumentation을 기반으로 자동으로 핀포인에서 처리합니다. 원리는 간단한게. 추적할 메소드를 대상으로 추적 코드를 앞뒤로 심는것으로 이해하면 됩니다.
  21. Pinpoint의 핵심 가치는 이 두가지를 기반으로 합니다. 분산 RPC추적이 중요한 이유는 네이버의 서비스가 복잡하기 때문입니다. 마이크로 서비스 아키텍쳐 등이 요즘 유행하고 있는데. 네이버에서는 이미 유사한 스타일로 서비스가 구성되고 있습니다. 그리고 코드를 수정하지 않는것 또한 중요합니다. 네이버의 서비스수가 엄청 많기 때문입니다.
  22. 좀더 쉽게 애플리케이션 적용예를 보겠습니다.
  23. 해당 애플리케이션에 pinpoint를 적용하면 아래와 같은 데이터를 얻을수 있습니다. 코드를 따라가 보겠습니다.
  24. Tomcat b로 원격 호출이 들어간것을 모습이구요.
  25. 이와 같은 성능 데이터를 핀포인트를 통해 얻을수 있구요. 이러한 성능 정보를 핀포인트가 어떻게 추적하지는 내부동작을 보겠습니다.
  26. 핀포인트는 메시지를 받으면 traceid라고 추적키의 집합을 생성합니다.
  27. 실제 데이터의 예는 이와 같습니다.
  28. 스프링 콘트롤러 메소드 정보를 레코딩하구요
  29. 원격 호출시 핀포인트에서 자동으로 추적에 필요한 traceId를 Get메시지에 세팅합니다.
  30. 태그된 리퀘스트가 원격지로 가게됩니다.
  31. 톰캣 b는 태크된 리퀘스트를 보고 자식 노드로 동작하게 되구요.
  32. Tomcatb의 로직이 종료하면 성능 데이터를 collector로 보내게 됩니다.
  33. Tomcat a의 로직이 종료하면 역시 성능 데이터를 collector로 보내게 되구요.
  34. 저장된 정보를 읽어서 보여주게 되면 이와 같은 성능 정보를 얻을수 있습니다.
  35. 이를 활용한 트러블슈팅 사래는 많습니다. 일단 데이터를 통해 대부분의 성능 문제를 바로바로 집어 낼수 있습니다. 서버맵 데이터와, 개별 request데이터를 살펴 보시면 느린 구간을 직관으로 잡아 낼수 있습니다.
  36. 핀포인트를 개발하면서 어려운 점이 있는데요. 핀포인트의 백앤드가 되는 하둡패밀리들이 굉장히 어렵습니다. 분산환경을 기반으로 하고 있어서 복잡하기도 하구요. 핀포인트 질문중에 가장많이 물어보는 빈도도 제일높은것 같습니다.
  37. 실제로도 어렵습니다. Hbase도 죽고, hadoop도 무한루프도 돌구요. 재시작해도 회복이 안되기도 했습니다. 이런 일이 발생하면 굉장히 난감한데. 제심정은
  38. 이랬습니다.
  39. 일단 이런 문제는 이미 다 해결된 상태고, 운영중인 버전을 너무 구버전을 써서 발생한 문제이기도 합니다. 버전업을 게을리한데서 나온 대가네요. 만약 문제가 생겨도 절대 당황하지 마시기 바랍니다. 성능데이터에 좀 문제 생겨도 비즈니스에는 큰문제가 없으니. 쉼호흡을 하고 한개씩 해결 하시면 됩니다. Pinpoint를 사용하는 사람은 자바 개발자분들이 많을건데. 기회삼아서 이번기회에 hbase도 보고, 하둡도 살펴보고, 기왕이면 소스도 보면 좋잖아요. 저도 다 아는게 아니기도 합니다.
  40. 보다 보면 전문가가 될수도 있으니 한번 해는것도 괜찮을것 같습니다. 어떤 사람도 처음부터 전문가가 아니잖아요, 해봐야 아는겁니다. 핀포인트를 하면서 기회가 되면 겸사겸사 해보는게 나쁘지는 않을거 같아요. 혹시 제가 말한것처럼 생각하신분 있나요? 그렇다면
  41. 세상일은 잘 모르는건데. 여기 듣는 여러분이 대상일수도 있어요.
  42. 계획대로네요. 최초 만들때부터 가능한 핀포인트 기술 선택을 향후에 충분히 활용할수 있을 만한것으로 선택했습니다. 아무래도 개인의 발전이나, 동기유발에 긍정적으로 접근하기 위해서요. 그리고 핀포인트도 오픈소스잖아요. 소스가 열려 있구요. 이것도 충분히 투자해 볼만하지 않아 합니다.
  43. 한편으로는 다행인점도 있습니다 중요설계 사상이 있는데. 백앤드가 죽어도, 어플리케이션은 정상으로 돌아가는것을 최우선 목표로 하고 있습니다.
  44. 그렇지만 사상은 사상이고, 이론과 현실은 다르잖아요, 말로는 다되죠. 사실 제가 앞에서는 저렇게 큰소리를 쳤는데. 알고보면 뒤에서
  45. 이랬습니다. 테스트나 이론으로는 검증했지만. 진짜로 그렇게 동작할지는 리얼환경에서 실제 동작해봐야 아는거라서요.
  46. 그런데 다행이 현실에서 검증되었습니다. 안심하셔도 됩니다. 그렇다고 해서 방심은 하면 안되니. 반드시 개발에서 먼저 검증해서 운영으로 넘어가는걸 추천드립니다. 이 과정에 버그가 발생하면 저희한테 꼭 알려주셨으면 하구요.
  47. 앞의 로드맵은 이와 같습니다. 코어 기능에만 집중하다 보니. 좀 미뤄진 경향이 있는데. 만들려고 하고있습니다. 실시간 데이터 같은 경우는 ActiveThread정도 필요하시잖아요. 이것도 만들려고 하고 있습니다. 점점더 발전시킬거니. 기대해주셔 아마 5월에도 D2 오픈 세미나가 있을것 같습니다. 관심있으시면 참석 부탁드리구요.
  48. github에 들어가셔서 별도 눌러주시구요. 들어주셔서 감사합니다.