Upload
woonduk-kang
View
1.076
Download
0
Embed Size (px)
Citation preview
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
10Hello() 호출정보
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
10Hello() 호출정보
-1Test() 호출정보
TraceData
내부동작
39
RowKey
TomcatA^시작시간^1
20 10
10Hello() 호출정보
-1Test() 호출정보
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