SlideShare ist ein Scribd-Unternehmen logo
1 von 51
Downloaden Sie, um offline zu lesen
오승현 (NAVER)
Pinpoint 를 이용해서 서버리스 플랫폼
Apache Openwhisk 트레이싱하기
오승현

SEONGHYUN OH
- NAVER PaaS
- Serverless Platform 개발 중
- Apache Openwhisk contributor
- Pinpoint Openwhisk 플러그인 개발 및 컨트리뷰션
Index
1. Apache Openwhisk 소개
2. Akka HTTP & Openwhisk 핀포인트 플러그인 소개
3. Pinpoint를 이용한 Openwhisk 트레이싱 데모
Apache Openwhisk?
Apache Openwhisk 소개
‣ 서버리스 플랫폼을 구축할 수 있는 아파치 오픈소스 프로젝트
‣ 이벤트에 반응하여 사용자가 미리 정의한 함수 코드(Action)를 실행
Apache Openwhisk 소개
‣ 함수 코드는 다양한 언어로 작성할 수 있음

(NodeJS, Python, Go, Java, Swift, PHP, Ruby …)
Apache Openwhisk 소개
‣ 다양한 언어로 작성된 액션들을 체이닝 하여 실행시킬 수 있음
Apache Openwhisk 소개
‣ 액션은 요청에 따라 자동으로 스케일링 되고 자원 활용을 최적화함

(액션 컨테이너가 필요에 따라 확장되고 사라짐)
Apache Openwhisk 소개
‣ Apache incubating project 

https://openwhisk.apache.org
Apache Openwhisk 소개
Openwhisk Pinpoint 플러그인
Why?
‣ 핀포인트가 적용된 서비스에서 액션을 호출했을 때 Distributed Tracing 불가능
‣ 사용자는 플랫폼 내부 동작을 전혀 알 수 없음
‣ 플랫폼 운영 관점에서 복잡한 분산 시스템에서 문제가 발생했을 때 원인 파악이 어려움
Service A Service B
serverless platform
navercorp.com
서버리스 플랫폼을 사용하면 

Tracing이 중단됨
첫 번째 관문, Scala로 작성된 Openwhisk
첫 번째 관문, Scala로 작성된 Openwhisk
‣ 수많은 플러그인 중 Scala 라이브러리를 지원하는 플러그인은 한개도 없었음
httpclient3, httpclient4, ning-asynchttpclient, resttemplate, gson, netty, jackson, cubrid-jdbc,
mysql-jdbc, mariadb-jdbc, postgresql-jdbc, jtds, dbcp, dbcp2, hikaricp, oracle-jdbc, jdk-http, json-
lib, redis, redis-lettuce, tomcat, thrift, user, arcus, google-httpclient, grpc, jetty, websphere,
spring, spring-boot, spring-webflux, ibatis, mybatis, okhttp, log4j, logback, dubbo, cassandra,
activemq-client, cxf, hystrix, jboss, vertx, resin, jsp, rxjava, rabbitmq, weblogic, undertow,
undertow-servlet, kafka, mongodb, fastjson, druid, hbase, redis-redisson, elasticsearch-bboss
소개 페이지에서도 Java, PHP에 대해서만..
Scala 어플리케이션에서 핀포인트 agent가 잘 동작 하나요..?
Scala Language
- Functional language
- Scala is compiled to java byte-codes and run on JVM
- Scala is compatible with Java
Scala Language
- Functional language
- Scala is compiled to java byte-codes and run on JVM
- Scala is compatible with Java
‣ Scala 애플리케이션에서 핀포인트 agent가 잘 동작하나요?
- 네, 플러그인이 없어서 모르셨겠지만… 핀포인트 agent가 동작합니다.
Pinpoint Agent에서 플러그인의 동작 방식
1. Pinpoint Agent 는 JVM이 시작할 때 활성화된 플러그인들을 로드
2. 각 플러그인은 타겟 클래스의 Bytecode를 변경(BCI, Bytecode Instrumentation)하여 타겟 메
소드에 Interceptor 를 추가하거나 새로운 필드(field)를 추가
3. 이후 타겟 메소드가 호출되면 추가된 Interceptor의 before과 after 메소드가 각각 타겟 메소드
앞과 뒤에서 호출되며 Trace 데이터를 기록함
=> BCI로 Bytecode를 변경하기 때문에 스칼라에 의해 Bytecode로 컴파일된 

타겟 클래스 명을 알아야 함
public static final java.lang.Object $anonfun$validateProperties$1$adapted(scala.collection.immutable.Map,
org.apache.openwhisk.common.Logging, java.lang.String);
Code:
0: aload_0
1: aload_1
2: aload_2
3: invokestatic #246 // Method $anonfun$validateProperties$1:(Lscala/collection/immutable/Map;Lorg/apache/openwhisk/
common/Logging;Ljava/lang/String;)Z
6: invokestatic #252 // Method scala/runtime/BoxesRunTime.boxToBoolean:(Z)Ljava/lang/Boolean;
9: are-turn
Scala의 JVM Bytecode
- 플러그인을 통해 타겟 메소드를 변형하려고 보니 Java와 다르게 Scala에 의해 bytecode 로 컴파일
된 클래스와 메소드 명에는 수많은 $ 기호가 포함
- javap -c common.scala.build.classes.scala.main.org.apache.openwhisk.common.Config$
$
클래스가 $로 끝남
$ $ $ $
메소드 이름에 $가 포함되기도
Scala로 컴파일된 JVM Bytecode (Case 1)
- 클래스 명에 $가 들어가는 경우 : Scala object
- Hello.class : Hello$.main() 메소드를 호출하는 wrapper 클래스
- Hello$.class : main 메소드의 실제 구현체
object를 사용하여 클래스 명에 

포함된 $는 어색하지만 

실제 구현체이므로 사용할 수 있음
object Hello {
def main(arg: Array[String]) {
println("hello world")
}
}
Scala로 컴파일된 JVM Bytecode (Case 1)
- 이외에도 클래스 명에 $가 들어가는 경우 : Value Class, Traits …
- 규칙을 가지고 컴파일 되는것을 확인
object Hello {
def main(arg: Array[String]) {
var inc = (x:Int) => x+1
var mul = (x: Int, y: Int) => x*y
}
}
Scala로 컴파일된 JVM Bytecode (Case 2)
- 문제는.. Scala 익명함수 ($anonfun$)
- Hello$.$anonfun$main$1 … (x:Int) => x+1
- Hello$.$anonfun$main$2 … (x: Int, y: Int) => x*y
익명함수의 이름은 규칙성을 가지지만
순서만 바뀌어도 언제든지 변경 가능한 값
첫 번째로 정의된 익명함수
두 번째로 정의된 익명함수
어플리케이션에서 사용하는 익명함수
- 함수형 언어 특성상 어쩔 수 없이 익명 함수를 직접 잡아야 하는 경우가 있음
- org.apache.openwhisk.http.BasicHttpService.$anonfun$assignId$2
- akka.http.scaladsl.server.directives.ExecutionDirectives.
$anonfun$handleExceptions$2
익명 함수는 pinpoint.config 설정으로 제공
- 파라미터와 메소드를 정확히 알아야 타겟 메소드를 변경할 수 있음
- 우선은 변경될 가능성이 있는 익명 함수는 설정(pinpoint.config)으로 제공하는 방식을 채택
profiler.openwhisk.transform.targetname=org.apache.openwhisk.http.BasicHttpService.
$anonfun$assignId$2
profiler.openwhisk.transform.targetparameter=org.apache.openwhisk.http.BasicHttpService,
boolean,akka.http.scaladsl.server.RequestContext
이름과 파라미터를 가지고 메소드를 찾는 방식으로 구현
가능한 익명 함수를 타겟 메소드로 잡는것은 최대한 피해야..
Akka 의 비동기 메시지 추적하기
- Akka는 오픈소스 프로젝트이며 동시성(concurrent) 및 분산 처리를 위한 툴킷으로 

액터(Actor) 프로그래밍 모델을 제공
- Openwhisk는 Actor 모델을 사용하기도 하고 Akka HTTP를 사용하여 HTTP 서버를 구축
- 사용자 요청의 첫 시작점인 Akka HTTP 플러그인을 만들기 시작 (by @lopiter)
Thread A
Akka Actor
- 액터가 수행하는 모든 것은 비동기적
(Asynchronous)으로 실행
- Akka의 Dispatcher는 스레드를 할당하고 메시지
를 액터에 푸쉬
- 사용자 요청이 동일한 스레드에서 동작한다는 것
을 

보장하지 않음
Actor
Actor
Actor
Mailbox
Mailbox
Mailbox
Thread B
Thread
ThreadLocal 에 Trace를 바인딩할 수 없음
“Trace objects are bound to the thread that first created them via
ThreadLocal and whenever the execution crosses a thread boundary,
trace objects are lost to the new thread”
Pinpoint는 Trace 객체를 

처음 생성된 스레드에 바인딩
새로운 스레드로 전환되면 

Trace 객체를 유실
핀포인트에서 Asynchronous task 처리
In order to trace tasks across thread boundaries, you must take care of
passing the current trace context over to the new thread. This is done
by injecting an AsyncContext into an object shared by both the
invocation thread and the execution thread.
AsyncContext 객체를 

특정 객체에 주입하여 공유해야 함
Akka HTTP Plugin 에서 비동기 처리
- Akka Http 의 라우터에서 비동기 처리를 위해 RequestContext 객체에 Pinpoint의
AsyncContext를 생성하여 주입
RequestContext
BCI를 통해 AsyncContext를 담을 수 있는 새로운 필드 추가된 상태
target.addField(AsyncContextAccessor.class)
Incoming HttpRequest
Router (Directives)
Pinpoint 

AsyncContext
AsyncContextAccessor 를 사용하여
AsyncContext 주입
Akka HTTP Plugin 에서 비동기 처리
- RequestContext는 요청의 흐름을 타고 비동기로 호출되는 complete, failed 메소드로 전달
됨
- 이때 AsyncContext를 RequestContext 객체에서 가져오고 Trace를 종료
RequestContextImpl

def complete()
RequestContextImpl

def failed()
RequestContext
Pinpoint 

AsyncContext
Trace 종료
Akka HTTP Plugin 구현
- 비동기로 동작하는 Akka HTTP 의 트레이싱 결과
비동기 컨텍스트(AsyncContext)로 동작
이제 Openwhisk도 추적해볼까요?
Welcome to the Scala Future
익명함수
익명함수
Future에 의한 비동기 호출 (Async stack trace)
Future에 의한 비동기 호출 (Async stack trace)
AsyncContext를 

매번 전달해야됨
Welcome to the Scala Future
- 트레이싱이 필요한 수많은 로직들이 Scala
Future API에 의해 비동기로 동작
- 익명함수로 호출되고 심지어는 인자를 

전달하지 않기도 함
- AsyncContext를 전달하기가 굉장히 어렵기
에 비동기 Trace를 유지할 방법을 찾아야 함
익명함수
익명함수
Future에 의한 비동기 호출 (Async stack trace)
Future에 의한 비동기 호출 (Async stack trace)
Openwhisk 의 TransactionId 를 활용
- Openwhisk의 TransactionId는 요청 흐름을 추적하고 로깅을 수월하게 하기 위해 

내부적으로 정의하여 사용되는 객체
- Scala의 암시적 파라미터(implicit parameter)를 통해 동기 또는 비동기적으로 호출되는 메소
드간에는 TransactionId 객체를 공유하며 컨텍스트를 유지
/**
* Receives a message and runs the router.
*/
def route: Route = {
assignId { implicit transid =>
respondWithHeader(transid.toHeader) {
/**
* Spawns a container in detached mode.
*
* @param image the image to start the container with
* @param args arguments for the docker run command
* @return id of the started container
*/
def run(image: String, args: Seq[String] = Seq.empty[String])
(implicit transid: TransactionId): Future[ContainerId]
요청의 처음 시작에서 

TransactionId 객체가 만들어지고 할당됨
TransactionId에 AsyncContext 주입
- AsyncContext는 Akka HTTP에서 만들어진 것을 사용
- Akka HTTP Plugin에서 시작된 AsyncContext를 통해 Trace를 지속할 수 있도록
RequestContext에 주입되어 있는 AsyncContext 를 다시 TransactionId 객체에 주입
TransactionId
Pinpoint 

AsyncContext
RequestContext
Pinpoint 

AsyncContext
Akka HTTP Plugin Openwhisk Plugin
TransactionId에 AsyncContext 주입
- 이후 트레이싱이 필요한 메소드들은 암시적 파라미터(implicit parameter)로 전달받은 

TransactionId의 AsyncContext 를 사용하여 AsyncTrace를 지속할 수 있음
TransactionId
Openwhisk Plugin
Pinpoint 

AsyncContext
/**
* Spawns a container in detached mode.
*
* @param image the image to start the container with
* @param args arguments for the docker run command
* @return id of the started container
*/
def run(image: String, args: Seq[String] = Seq.empty[String])
(implicit transid: TransactionId): Future[ContainerId]
이 경우 플러그인에서 run 메소드를 

Transform 하면 TransactionId 객체 접근 가능
그런데..
몇 일 지나니 플러그인이 동작을 안한다?
힘들게 만들었는데..
Openwhisk 는 incubating 프로젝트
- 아직까지 공식 릴리즈 버전이 없음
- 거의 매일 바뀌는 코드

(하지만, 플러그인을 계속해서 수정할 수 없음)
- => 대안이 필요
기존 Interceptor의 방식은?
profiler.openwhisk.transform.targetname=org.apache.openwhisk.http.BasicHttpService.
$anonfun$assignId$2
profiler.openwhisk.transform.targetparameter=org.apache.openwhisk.http.BasicHttpService,
boolean,akka.http.scaladsl.server.RequestContext
1. 타겟 메소드를 설정에서 찾음 

(메소드 이름과 파라미터)
org.apache.openwhisk.http.BasicHttpService.$anonfun$assignId$2() {
// method code
}
2. BCI를 통해 타겟 메소드에 Interceptor를 주입함
3. Interceptor는 before, after 메소드에서 

Trace 데이터를 기록함
Interceptor.before()
Interceptor.after()
* 변경 가능성이 있는 수많은 내부 메소드에 대해서 이 작업을 해야 함!
최소한의 메소드만 변형할수는 없을까?
- Openwhisk는 내부적으로 로그를 출력하거나 메트릭을 수집할 때 특정 메소드의 실행 시간을 

측정하기 위해 TransactionId 에 구현된 started(), finished() 메소드를 사용 중
메소드 시작 지점에 started 호출
종료 지점에 finished 호출
started, finished 메소드를 Transform
- 하나의 메소드에서 트레이싱이 이루어지는 

기존의 방식을 두 개의 메소드로 분리
def started() {
Interceptor.before()
// something
Interceptor.after()
}
def finished() {
Interceptor.before()
// something
Interceptor.after()
}
로직 실행
started 메소드가 호출되면 Interceptor 에서 Trace 시작
(일반적인 Interceptor와 다르게 Trace를 종료하지 않음)
이후 호출되는 finished 메소드에서 Trace 종료
(started 메소드에서 시작된 Trace를 종료함)
Interceptor.before()
Interceptor.before()
Interceptor.after()
Interceptor.after()
def someMethod() {
}
started, finished 메소드를 Transform
- 실제 메소드명이 아닌 started 메소드로 전달된 로그 마커를 메소드 이름으로 기록하고 

로그 메시지는 새로운 marker.message annotation을 정의하고 기록
[2019-07-08T08:01:21.644Z] [INFO] [#tid_uZ9wiZOezssfabRZW2wcVPHxWqys2aF2]
[ActionsApi] action action activation id: 81355efc90c847ddb55efc90c887dd74
[marker:controller_loadbalancer_start:8760]
이제는?
- 어플리케이션에서 started, finished 메소드로 로그를 찍어주기만 하면 Pinpoint에서 Tracing 가능
- 플러그인 관리 주기가 길어짐 (최소 6개월 이상)
컴포넌트간의 메시지 전달하기
NGINX
Controller
Invoker
CouchDB
Invoker
RestAPI + 인증 및 권한
컨테이너 구동,
함수 초기화 및 실행
액션 코드 및
실행 결과 저장
컴포넌트간의 메시지 전달하기
- Controller -> Invoker 컴포넌트간에는 ActivationMessage 객체를 주고 받음
- OpenTracing에서 사용하는 traceContext 필드에 플러그인에서 Pinpoint Transaction 정보
를 주입
Kafka에 메시지를 보내기 전에 traceContext를 조작
컴포넌트간의 메시지 전달하기
- Invoker는 ActivationMessage를 받으면 traceContext 필드에서 PinpointTransaction 정보
를 가지고 다시 Tracing을 시작
Invoker
다 잊어버리셔도 됩니다
‣ Pinpoint agent 를 어플리케이션 실행 시 추가하면 바로 사용 가능 (핀포인트의 장점)
‣ -javaagent:${pinpointPath}/pinpoint-bootstrap-1.8.3.jar

-Dpinpoint.applicationName=ApplicationName

-Dpinpoint.agentId=AgentId
참 쉽죠..?
Openwhisk 플랫폼 Tracing 데모
정리하면..
‣ 핀포인트로 스칼라(Scala) 어플리케이션을 Tracing할 수 있습니다.
‣ 익명함수는 최대한 피하고.. 피할 수 없다면 설정으로 하는게 좋습니다.

(더 좋은 방법이 있다면 알려주세요!)
‣ 비동기 호출을 요청하기 위해 AsyncContext를 전달 하는 방법을 먼저 찾아야 합니다.
‣ 코드 변경이 많은 프로젝트는.. 공통 인터페이스를 찾아 Transform 하면 좋습니다.
Thank you

Weitere ähnliche Inhalte

Was ist angesagt?

Amazon Cognito使って認証したい?それならSpring Security使いましょう!
Amazon Cognito使って認証したい?それならSpring Security使いましょう!Amazon Cognito使って認証したい?それならSpring Security使いましょう!
Amazon Cognito使って認証したい?それならSpring Security使いましょう!
Ryosuke Uchitate
 

Was ist angesagt? (20)

AWSのログ管理ベストプラクティス
AWSのログ管理ベストプラクティスAWSのログ管理ベストプラクティス
AWSのログ管理ベストプラクティス
 
4. 대용량 아키텍쳐 설계 패턴
4. 대용량 아키텍쳐 설계 패턴4. 대용량 아키텍쳐 설계 패턴
4. 대용량 아키텍쳐 설계 패턴
 
Jbatch実践入門 #jdt2015
Jbatch実践入門 #jdt2015Jbatch実践入門 #jdt2015
Jbatch実践入門 #jdt2015
 
Docker를 활용한 손쉬운 ECS 활용기 - 김민태 (AUSG) :: AWS Community Day Online 2021
Docker를 활용한 손쉬운 ECS 활용기 - 김민태 (AUSG) :: AWS Community Day Online 2021Docker를 활용한 손쉬운 ECS 활용기 - 김민태 (AUSG) :: AWS Community Day Online 2021
Docker를 활용한 손쉬운 ECS 활용기 - 김민태 (AUSG) :: AWS Community Day Online 2021
 
시니어가 들려주는 "내가 알고 있는 걸 당신도 알게 된다면"
시니어가 들려주는 "내가 알고 있는 걸 당신도 알게 된다면"시니어가 들려주는 "내가 알고 있는 걸 당신도 알게 된다면"
시니어가 들려주는 "내가 알고 있는 걸 당신도 알게 된다면"
 
[NDC17] Kubernetes로 개발서버 간단히 찍어내기
[NDC17] Kubernetes로 개발서버 간단히 찍어내기[NDC17] Kubernetes로 개발서버 간단히 찍어내기
[NDC17] Kubernetes로 개발서버 간단히 찍어내기
 
HCL AppScan 10 のご紹介
HCL AppScan 10 のご紹介HCL AppScan 10 のご紹介
HCL AppScan 10 のご紹介
 
파이썬 생존 안내서 (자막)
파이썬 생존 안내서 (자막)파이썬 생존 안내서 (자막)
파이썬 생존 안내서 (자막)
 
CloudFront経由でのCORS利用
CloudFront経由でのCORS利用CloudFront経由でのCORS利用
CloudFront経由でのCORS利用
 
쿠키런: 킹덤 대규모 인프라 및 서버 운영 사례 공유 [데브시스터즈 - 레벨 200] - 발표자: 용찬호, R&D 엔지니어, 데브시스터즈 ...
쿠키런: 킹덤 대규모 인프라 및 서버 운영 사례 공유 [데브시스터즈 - 레벨 200] - 발표자: 용찬호, R&D 엔지니어, 데브시스터즈 ...쿠키런: 킹덤 대규모 인프라 및 서버 운영 사례 공유 [데브시스터즈 - 레벨 200] - 발표자: 용찬호, R&D 엔지니어, 데브시스터즈 ...
쿠키런: 킹덤 대규모 인프라 및 서버 운영 사례 공유 [데브시스터즈 - 레벨 200] - 발표자: 용찬호, R&D 엔지니어, 데브시스터즈 ...
 
Windows Registered I/O (RIO) vs IOCP
Windows Registered I/O (RIO) vs IOCPWindows Registered I/O (RIO) vs IOCP
Windows Registered I/O (RIO) vs IOCP
 
DI(依存性注入)について
DI(依存性注入)についてDI(依存性注入)について
DI(依存性注入)について
 
Windows IOCP vs Linux EPOLL Performance Comparison
Windows IOCP vs Linux EPOLL Performance ComparisonWindows IOCP vs Linux EPOLL Performance Comparison
Windows IOCP vs Linux EPOLL Performance Comparison
 
비동기 어플리케이션 모니터링과 밀당하기
비동기 어플리케이션 모니터링과 밀당하기비동기 어플리케이션 모니터링과 밀당하기
비동기 어플리케이션 모니터링과 밀당하기
 
[NDC18] 야생의 땅 듀랑고의 데이터 엔지니어링 이야기: 로그 시스템 구축 경험 공유 (2부)
[NDC18] 야생의 땅 듀랑고의 데이터 엔지니어링 이야기: 로그 시스템 구축 경험 공유 (2부)[NDC18] 야생의 땅 듀랑고의 데이터 엔지니어링 이야기: 로그 시스템 구축 경험 공유 (2부)
[NDC18] 야생의 땅 듀랑고의 데이터 엔지니어링 이야기: 로그 시스템 구축 경험 공유 (2부)
 
Amazon Cognito使って認証したい?それならSpring Security使いましょう!
Amazon Cognito使って認証したい?それならSpring Security使いましょう!Amazon Cognito使って認証したい?それならSpring Security使いましょう!
Amazon Cognito使って認証したい?それならSpring Security使いましょう!
 
Message Queue 가용성, 신뢰성을 위한 RabbitMQ Server, Client 구성
Message Queue 가용성, 신뢰성을 위한 RabbitMQ Server, Client 구성Message Queue 가용성, 신뢰성을 위한 RabbitMQ Server, Client 구성
Message Queue 가용성, 신뢰성을 위한 RabbitMQ Server, Client 구성
 
Swagger ではない OpenAPI Specification 3.0 による API サーバー開発
Swagger ではない OpenAPI Specification 3.0 による API サーバー開発Swagger ではない OpenAPI Specification 3.0 による API サーバー開発
Swagger ではない OpenAPI Specification 3.0 による API サーバー開発
 
[Aurora事例祭り]Amazon Aurora を使いこなすためのベストプラクティス
[Aurora事例祭り]Amazon Aurora を使いこなすためのベストプラクティス[Aurora事例祭り]Amazon Aurora を使いこなすためのベストプラクティス
[Aurora事例祭り]Amazon Aurora を使いこなすためのベストプラクティス
 
SSRF対策としてAmazonから発表されたIMDSv2の効果と破り方
SSRF対策としてAmazonから発表されたIMDSv2の効果と破り方SSRF対策としてAmazonから発表されたIMDSv2の効果と破り方
SSRF対策としてAmazonから発表されたIMDSv2の効果と破り方
 

Ähnlich wie [네이버오픈소스세미나] Pinpoint를 이용해서 서버리스 플랫폼 Apache Openwhisk 트레이싱하기 - 오승현

[Hello world 오픈세미나]open api client개발
[Hello world 오픈세미나]open api client개발[Hello world 오픈세미나]open api client개발
[Hello world 오픈세미나]open api client개발
NAVER D2
 

Ähnlich wie [네이버오픈소스세미나] Pinpoint를 이용해서 서버리스 플랫폼 Apache Openwhisk 트레이싱하기 - 오승현 (20)

Javascript 조금 더 잘 알기
Javascript 조금 더 잘 알기Javascript 조금 더 잘 알기
Javascript 조금 더 잘 알기
 
Tensorflow service & Machine Learning
Tensorflow service & Machine LearningTensorflow service & Machine Learning
Tensorflow service & Machine Learning
 
우린 같은 곳을 바라 보고 있나요?
우린 같은 곳을 바라 보고 있나요?우린 같은 곳을 바라 보고 있나요?
우린 같은 곳을 바라 보고 있나요?
 
Netty 세미나
Netty 세미나Netty 세미나
Netty 세미나
 
[오픈소스컨설팅]쿠버네티스를 활용한 개발환경 구축
[오픈소스컨설팅]쿠버네티스를 활용한 개발환경 구축[오픈소스컨설팅]쿠버네티스를 활용한 개발환경 구축
[오픈소스컨설팅]쿠버네티스를 활용한 개발환경 구축
 
Springmvc
SpringmvcSpringmvc
Springmvc
 
Akka.NET 으로 만드는 온라인 게임 서버 (NDC2016)
Akka.NET 으로 만드는 온라인 게임 서버 (NDC2016)Akka.NET 으로 만드는 온라인 게임 서버 (NDC2016)
Akka.NET 으로 만드는 온라인 게임 서버 (NDC2016)
 
11st Legacy Application의 Spring Cloud 기반 MicroServices로 전환 개발 사례
11st Legacy Application의 Spring Cloud 기반 MicroServices로 전환 개발 사례11st Legacy Application의 Spring Cloud 기반 MicroServices로 전환 개발 사례
11st Legacy Application의 Spring Cloud 기반 MicroServices로 전환 개발 사례
 
Spring boot DI
Spring boot DISpring boot DI
Spring boot DI
 
C# Game Server
C# Game ServerC# Game Server
C# Game Server
 
파이썬 웹 프로그래밍 2탄
파이썬 웹 프로그래밍 2탄 파이썬 웹 프로그래밍 2탄
파이썬 웹 프로그래밍 2탄
 
Progressive Web App(PWA) 테코톡 발표자료 - 마르코(장원석)
Progressive Web App(PWA) 테코톡 발표자료 - 마르코(장원석)Progressive Web App(PWA) 테코톡 발표자료 - 마르코(장원석)
Progressive Web App(PWA) 테코톡 발표자료 - 마르코(장원석)
 
[213]monitoringwithscouter 이건희
[213]monitoringwithscouter 이건희[213]monitoringwithscouter 이건희
[213]monitoringwithscouter 이건희
 
One-day-codelab
One-day-codelabOne-day-codelab
One-day-codelab
 
K8s beginner 2_advanced_ep02_201904221130_post
K8s beginner 2_advanced_ep02_201904221130_postK8s beginner 2_advanced_ep02_201904221130_post
K8s beginner 2_advanced_ep02_201904221130_post
 
[Hello world 오픈세미나]open api client개발
[Hello world 오픈세미나]open api client개발[Hello world 오픈세미나]open api client개발
[Hello world 오픈세미나]open api client개발
 
[236] 카카오의데이터파이프라인 윤도영
[236] 카카오의데이터파이프라인 윤도영[236] 카카오의데이터파이프라인 윤도영
[236] 카카오의데이터파이프라인 윤도영
 
아해2019 SpringAOP 문겸
아해2019 SpringAOP 문겸아해2019 SpringAOP 문겸
아해2019 SpringAOP 문겸
 
Node.js 기본
Node.js 기본Node.js 기본
Node.js 기본
 
ECMAScript 6의 새로운 것들!
ECMAScript 6의 새로운 것들!ECMAScript 6의 새로운 것들!
ECMAScript 6의 새로운 것들!
 

Mehr von NAVER Engineering

Mehr von NAVER Engineering (20)

React vac pattern
React vac patternReact vac pattern
React vac pattern
 
디자인 시스템에 직방 ZUIX
디자인 시스템에 직방 ZUIX디자인 시스템에 직방 ZUIX
디자인 시스템에 직방 ZUIX
 
진화하는 디자인 시스템(걸음마 편)
진화하는 디자인 시스템(걸음마 편)진화하는 디자인 시스템(걸음마 편)
진화하는 디자인 시스템(걸음마 편)
 
서비스 운영을 위한 디자인시스템 프로젝트
서비스 운영을 위한 디자인시스템 프로젝트서비스 운영을 위한 디자인시스템 프로젝트
서비스 운영을 위한 디자인시스템 프로젝트
 
BPL(Banksalad Product Language) 무야호
BPL(Banksalad Product Language) 무야호BPL(Banksalad Product Language) 무야호
BPL(Banksalad Product Language) 무야호
 
이번 생에 디자인 시스템은 처음이라
이번 생에 디자인 시스템은 처음이라이번 생에 디자인 시스템은 처음이라
이번 생에 디자인 시스템은 처음이라
 
날고 있는 여러 비행기 넘나 들며 정비하기
날고 있는 여러 비행기 넘나 들며 정비하기날고 있는 여러 비행기 넘나 들며 정비하기
날고 있는 여러 비행기 넘나 들며 정비하기
 
쏘카프레임 구축 배경과 과정
 쏘카프레임 구축 배경과 과정 쏘카프레임 구축 배경과 과정
쏘카프레임 구축 배경과 과정
 
플랫폼 디자이너 없이 디자인 시스템을 구축하는 프로덕트 디자이너의 우당탕탕 고통 연대기
플랫폼 디자이너 없이 디자인 시스템을 구축하는 프로덕트 디자이너의 우당탕탕 고통 연대기플랫폼 디자이너 없이 디자인 시스템을 구축하는 프로덕트 디자이너의 우당탕탕 고통 연대기
플랫폼 디자이너 없이 디자인 시스템을 구축하는 프로덕트 디자이너의 우당탕탕 고통 연대기
 
200820 NAVER TECH CONCERT 15_Code Review is Horse(코드리뷰는 말이야)(feat.Latte)
200820 NAVER TECH CONCERT 15_Code Review is Horse(코드리뷰는 말이야)(feat.Latte)200820 NAVER TECH CONCERT 15_Code Review is Horse(코드리뷰는 말이야)(feat.Latte)
200820 NAVER TECH CONCERT 15_Code Review is Horse(코드리뷰는 말이야)(feat.Latte)
 
200819 NAVER TECH CONCERT 03_화려한 코루틴이 내 앱을 감싸네! 코루틴으로 작성해보는 깔끔한 비동기 코드
200819 NAVER TECH CONCERT 03_화려한 코루틴이 내 앱을 감싸네! 코루틴으로 작성해보는 깔끔한 비동기 코드200819 NAVER TECH CONCERT 03_화려한 코루틴이 내 앱을 감싸네! 코루틴으로 작성해보는 깔끔한 비동기 코드
200819 NAVER TECH CONCERT 03_화려한 코루틴이 내 앱을 감싸네! 코루틴으로 작성해보는 깔끔한 비동기 코드
 
200819 NAVER TECH CONCERT 10_맥북에서도 아이맥프로에서 빌드하는 것처럼 빌드 속도 빠르게 하기
200819 NAVER TECH CONCERT 10_맥북에서도 아이맥프로에서 빌드하는 것처럼 빌드 속도 빠르게 하기200819 NAVER TECH CONCERT 10_맥북에서도 아이맥프로에서 빌드하는 것처럼 빌드 속도 빠르게 하기
200819 NAVER TECH CONCERT 10_맥북에서도 아이맥프로에서 빌드하는 것처럼 빌드 속도 빠르게 하기
 
200819 NAVER TECH CONCERT 08_성능을 고민하는 슬기로운 개발자 생활
200819 NAVER TECH CONCERT 08_성능을 고민하는 슬기로운 개발자 생활200819 NAVER TECH CONCERT 08_성능을 고민하는 슬기로운 개발자 생활
200819 NAVER TECH CONCERT 08_성능을 고민하는 슬기로운 개발자 생활
 
200819 NAVER TECH CONCERT 05_모르면 손해보는 Android 디버깅/분석 꿀팁 대방출
200819 NAVER TECH CONCERT 05_모르면 손해보는 Android 디버깅/분석 꿀팁 대방출200819 NAVER TECH CONCERT 05_모르면 손해보는 Android 디버깅/분석 꿀팁 대방출
200819 NAVER TECH CONCERT 05_모르면 손해보는 Android 디버깅/분석 꿀팁 대방출
 
200819 NAVER TECH CONCERT 09_Case.xcodeproj - 좋은 동료로 거듭나기 위한 노하우
200819 NAVER TECH CONCERT 09_Case.xcodeproj - 좋은 동료로 거듭나기 위한 노하우200819 NAVER TECH CONCERT 09_Case.xcodeproj - 좋은 동료로 거듭나기 위한 노하우
200819 NAVER TECH CONCERT 09_Case.xcodeproj - 좋은 동료로 거듭나기 위한 노하우
 
200820 NAVER TECH CONCERT 14_야 너두 할 수 있어. 비전공자, COBOL 개발자를 거쳐 네이버에서 FE 개발하게 된...
200820 NAVER TECH CONCERT 14_야 너두 할 수 있어. 비전공자, COBOL 개발자를 거쳐 네이버에서 FE 개발하게 된...200820 NAVER TECH CONCERT 14_야 너두 할 수 있어. 비전공자, COBOL 개발자를 거쳐 네이버에서 FE 개발하게 된...
200820 NAVER TECH CONCERT 14_야 너두 할 수 있어. 비전공자, COBOL 개발자를 거쳐 네이버에서 FE 개발하게 된...
 
200820 NAVER TECH CONCERT 13_네이버에서 오픈 소스 개발을 통해 성장하는 방법
200820 NAVER TECH CONCERT 13_네이버에서 오픈 소스 개발을 통해 성장하는 방법200820 NAVER TECH CONCERT 13_네이버에서 오픈 소스 개발을 통해 성장하는 방법
200820 NAVER TECH CONCERT 13_네이버에서 오픈 소스 개발을 통해 성장하는 방법
 
200820 NAVER TECH CONCERT 12_상반기 네이버 인턴을 돌아보며
200820 NAVER TECH CONCERT 12_상반기 네이버 인턴을 돌아보며200820 NAVER TECH CONCERT 12_상반기 네이버 인턴을 돌아보며
200820 NAVER TECH CONCERT 12_상반기 네이버 인턴을 돌아보며
 
200820 NAVER TECH CONCERT 11_빠르게 성장하는 슈퍼루키로 거듭나기
200820 NAVER TECH CONCERT 11_빠르게 성장하는 슈퍼루키로 거듭나기200820 NAVER TECH CONCERT 11_빠르게 성장하는 슈퍼루키로 거듭나기
200820 NAVER TECH CONCERT 11_빠르게 성장하는 슈퍼루키로 거듭나기
 
200819 NAVER TECH CONCERT 07_신입 iOS 개발자 개발업무 적응기
200819 NAVER TECH CONCERT 07_신입 iOS 개발자 개발업무 적응기200819 NAVER TECH CONCERT 07_신입 iOS 개발자 개발업무 적응기
200819 NAVER TECH CONCERT 07_신입 iOS 개발자 개발업무 적응기
 

Kürzlich hochgeladen

Kürzlich hochgeladen (8)

JMP를 활용한 가속열화 분석 사례
JMP를 활용한 가속열화 분석 사례JMP를 활용한 가속열화 분석 사례
JMP를 활용한 가속열화 분석 사례
 
데이터 분석 문제 해결을 위한 나의 JMP 활용법
데이터 분석 문제 해결을 위한 나의 JMP 활용법데이터 분석 문제 해결을 위한 나의 JMP 활용법
데이터 분석 문제 해결을 위한 나의 JMP 활용법
 
실험 설계의 평가 방법: Custom Design을 중심으로 반응인자 최적화 및 Criteria 해석
실험 설계의 평가 방법: Custom Design을 중심으로 반응인자 최적화 및 Criteria 해석실험 설계의 평가 방법: Custom Design을 중심으로 반응인자 최적화 및 Criteria 해석
실험 설계의 평가 방법: Custom Design을 중심으로 반응인자 최적화 및 Criteria 해석
 
(독서광) 인간이 초대한 대형 참사 - 대형 참사가 일어날 때까지 사람들은 무엇을 하고 있었는가?
(독서광) 인간이 초대한 대형 참사 - 대형 참사가 일어날 때까지 사람들은 무엇을 하고 있었는가?(독서광) 인간이 초대한 대형 참사 - 대형 참사가 일어날 때까지 사람들은 무엇을 하고 있었는가?
(독서광) 인간이 초대한 대형 참사 - 대형 참사가 일어날 때까지 사람들은 무엇을 하고 있었는가?
 
JMP가 걸어온 여정, 새로운 도약 JMP 18!
JMP가 걸어온 여정, 새로운 도약 JMP 18!JMP가 걸어온 여정, 새로운 도약 JMP 18!
JMP가 걸어온 여정, 새로운 도약 JMP 18!
 
JMP 기능의 확장 및 내재화의 핵심 JMP-Python 소개
JMP 기능의 확장 및 내재화의 핵심 JMP-Python 소개JMP 기능의 확장 및 내재화의 핵심 JMP-Python 소개
JMP 기능의 확장 및 내재화의 핵심 JMP-Python 소개
 
JMP를 활용한 전자/반도체 산업 Yield Enhancement Methodology
JMP를 활용한 전자/반도체 산업 Yield Enhancement MethodologyJMP를 활용한 전자/반도체 산업 Yield Enhancement Methodology
JMP를 활용한 전자/반도체 산업 Yield Enhancement Methodology
 
공학 관점에서 바라본 JMP 머신러닝 최적화
공학 관점에서 바라본 JMP 머신러닝 최적화공학 관점에서 바라본 JMP 머신러닝 최적화
공학 관점에서 바라본 JMP 머신러닝 최적화
 

[네이버오픈소스세미나] Pinpoint를 이용해서 서버리스 플랫폼 Apache Openwhisk 트레이싱하기 - 오승현

  • 1. 오승현 (NAVER) Pinpoint 를 이용해서 서버리스 플랫폼 Apache Openwhisk 트레이싱하기
  • 2. 오승현
 SEONGHYUN OH - NAVER PaaS - Serverless Platform 개발 중 - Apache Openwhisk contributor - Pinpoint Openwhisk 플러그인 개발 및 컨트리뷰션
  • 3. Index 1. Apache Openwhisk 소개 2. Akka HTTP & Openwhisk 핀포인트 플러그인 소개 3. Pinpoint를 이용한 Openwhisk 트레이싱 데모
  • 5. Apache Openwhisk 소개 ‣ 서버리스 플랫폼을 구축할 수 있는 아파치 오픈소스 프로젝트 ‣ 이벤트에 반응하여 사용자가 미리 정의한 함수 코드(Action)를 실행
  • 6. Apache Openwhisk 소개 ‣ 함수 코드는 다양한 언어로 작성할 수 있음
 (NodeJS, Python, Go, Java, Swift, PHP, Ruby …)
  • 7. Apache Openwhisk 소개 ‣ 다양한 언어로 작성된 액션들을 체이닝 하여 실행시킬 수 있음
  • 8. Apache Openwhisk 소개 ‣ 액션은 요청에 따라 자동으로 스케일링 되고 자원 활용을 최적화함
 (액션 컨테이너가 필요에 따라 확장되고 사라짐)
  • 9. Apache Openwhisk 소개 ‣ Apache incubating project 
 https://openwhisk.apache.org
  • 12. Why? ‣ 핀포인트가 적용된 서비스에서 액션을 호출했을 때 Distributed Tracing 불가능 ‣ 사용자는 플랫폼 내부 동작을 전혀 알 수 없음 ‣ 플랫폼 운영 관점에서 복잡한 분산 시스템에서 문제가 발생했을 때 원인 파악이 어려움 Service A Service B serverless platform navercorp.com 서버리스 플랫폼을 사용하면 
 Tracing이 중단됨
  • 13. 첫 번째 관문, Scala로 작성된 Openwhisk
  • 14. 첫 번째 관문, Scala로 작성된 Openwhisk ‣ 수많은 플러그인 중 Scala 라이브러리를 지원하는 플러그인은 한개도 없었음 httpclient3, httpclient4, ning-asynchttpclient, resttemplate, gson, netty, jackson, cubrid-jdbc, mysql-jdbc, mariadb-jdbc, postgresql-jdbc, jtds, dbcp, dbcp2, hikaricp, oracle-jdbc, jdk-http, json- lib, redis, redis-lettuce, tomcat, thrift, user, arcus, google-httpclient, grpc, jetty, websphere, spring, spring-boot, spring-webflux, ibatis, mybatis, okhttp, log4j, logback, dubbo, cassandra, activemq-client, cxf, hystrix, jboss, vertx, resin, jsp, rxjava, rabbitmq, weblogic, undertow, undertow-servlet, kafka, mongodb, fastjson, druid, hbase, redis-redisson, elasticsearch-bboss
  • 15. 소개 페이지에서도 Java, PHP에 대해서만.. Scala 어플리케이션에서 핀포인트 agent가 잘 동작 하나요..?
  • 16. Scala Language - Functional language - Scala is compiled to java byte-codes and run on JVM - Scala is compatible with Java
  • 17. Scala Language - Functional language - Scala is compiled to java byte-codes and run on JVM - Scala is compatible with Java ‣ Scala 애플리케이션에서 핀포인트 agent가 잘 동작하나요? - 네, 플러그인이 없어서 모르셨겠지만… 핀포인트 agent가 동작합니다.
  • 18. Pinpoint Agent에서 플러그인의 동작 방식 1. Pinpoint Agent 는 JVM이 시작할 때 활성화된 플러그인들을 로드 2. 각 플러그인은 타겟 클래스의 Bytecode를 변경(BCI, Bytecode Instrumentation)하여 타겟 메 소드에 Interceptor 를 추가하거나 새로운 필드(field)를 추가 3. 이후 타겟 메소드가 호출되면 추가된 Interceptor의 before과 after 메소드가 각각 타겟 메소드 앞과 뒤에서 호출되며 Trace 데이터를 기록함 => BCI로 Bytecode를 변경하기 때문에 스칼라에 의해 Bytecode로 컴파일된 
 타겟 클래스 명을 알아야 함
  • 19. public static final java.lang.Object $anonfun$validateProperties$1$adapted(scala.collection.immutable.Map, org.apache.openwhisk.common.Logging, java.lang.String); Code: 0: aload_0 1: aload_1 2: aload_2 3: invokestatic #246 // Method $anonfun$validateProperties$1:(Lscala/collection/immutable/Map;Lorg/apache/openwhisk/ common/Logging;Ljava/lang/String;)Z 6: invokestatic #252 // Method scala/runtime/BoxesRunTime.boxToBoolean:(Z)Ljava/lang/Boolean; 9: are-turn Scala의 JVM Bytecode - 플러그인을 통해 타겟 메소드를 변형하려고 보니 Java와 다르게 Scala에 의해 bytecode 로 컴파일 된 클래스와 메소드 명에는 수많은 $ 기호가 포함 - javap -c common.scala.build.classes.scala.main.org.apache.openwhisk.common.Config$ $ 클래스가 $로 끝남 $ $ $ $ 메소드 이름에 $가 포함되기도
  • 20. Scala로 컴파일된 JVM Bytecode (Case 1) - 클래스 명에 $가 들어가는 경우 : Scala object - Hello.class : Hello$.main() 메소드를 호출하는 wrapper 클래스 - Hello$.class : main 메소드의 실제 구현체 object를 사용하여 클래스 명에 
 포함된 $는 어색하지만 
 실제 구현체이므로 사용할 수 있음 object Hello { def main(arg: Array[String]) { println("hello world") } }
  • 21. Scala로 컴파일된 JVM Bytecode (Case 1) - 이외에도 클래스 명에 $가 들어가는 경우 : Value Class, Traits … - 규칙을 가지고 컴파일 되는것을 확인
  • 22. object Hello { def main(arg: Array[String]) { var inc = (x:Int) => x+1 var mul = (x: Int, y: Int) => x*y } } Scala로 컴파일된 JVM Bytecode (Case 2) - 문제는.. Scala 익명함수 ($anonfun$) - Hello$.$anonfun$main$1 … (x:Int) => x+1 - Hello$.$anonfun$main$2 … (x: Int, y: Int) => x*y 익명함수의 이름은 규칙성을 가지지만 순서만 바뀌어도 언제든지 변경 가능한 값 첫 번째로 정의된 익명함수 두 번째로 정의된 익명함수
  • 23. 어플리케이션에서 사용하는 익명함수 - 함수형 언어 특성상 어쩔 수 없이 익명 함수를 직접 잡아야 하는 경우가 있음 - org.apache.openwhisk.http.BasicHttpService.$anonfun$assignId$2 - akka.http.scaladsl.server.directives.ExecutionDirectives. $anonfun$handleExceptions$2
  • 24. 익명 함수는 pinpoint.config 설정으로 제공 - 파라미터와 메소드를 정확히 알아야 타겟 메소드를 변경할 수 있음 - 우선은 변경될 가능성이 있는 익명 함수는 설정(pinpoint.config)으로 제공하는 방식을 채택 profiler.openwhisk.transform.targetname=org.apache.openwhisk.http.BasicHttpService. $anonfun$assignId$2 profiler.openwhisk.transform.targetparameter=org.apache.openwhisk.http.BasicHttpService, boolean,akka.http.scaladsl.server.RequestContext 이름과 파라미터를 가지고 메소드를 찾는 방식으로 구현 가능한 익명 함수를 타겟 메소드로 잡는것은 최대한 피해야..
  • 25. Akka 의 비동기 메시지 추적하기 - Akka는 오픈소스 프로젝트이며 동시성(concurrent) 및 분산 처리를 위한 툴킷으로 
 액터(Actor) 프로그래밍 모델을 제공 - Openwhisk는 Actor 모델을 사용하기도 하고 Akka HTTP를 사용하여 HTTP 서버를 구축 - 사용자 요청의 첫 시작점인 Akka HTTP 플러그인을 만들기 시작 (by @lopiter)
  • 26. Thread A Akka Actor - 액터가 수행하는 모든 것은 비동기적 (Asynchronous)으로 실행 - Akka의 Dispatcher는 스레드를 할당하고 메시지 를 액터에 푸쉬 - 사용자 요청이 동일한 스레드에서 동작한다는 것 을 
 보장하지 않음 Actor Actor Actor Mailbox Mailbox Mailbox Thread B Thread
  • 27. ThreadLocal 에 Trace를 바인딩할 수 없음 “Trace objects are bound to the thread that first created them via ThreadLocal and whenever the execution crosses a thread boundary, trace objects are lost to the new thread” Pinpoint는 Trace 객체를 
 처음 생성된 스레드에 바인딩 새로운 스레드로 전환되면 
 Trace 객체를 유실
  • 28. 핀포인트에서 Asynchronous task 처리 In order to trace tasks across thread boundaries, you must take care of passing the current trace context over to the new thread. This is done by injecting an AsyncContext into an object shared by both the invocation thread and the execution thread. AsyncContext 객체를 
 특정 객체에 주입하여 공유해야 함
  • 29. Akka HTTP Plugin 에서 비동기 처리 - Akka Http 의 라우터에서 비동기 처리를 위해 RequestContext 객체에 Pinpoint의 AsyncContext를 생성하여 주입 RequestContext BCI를 통해 AsyncContext를 담을 수 있는 새로운 필드 추가된 상태 target.addField(AsyncContextAccessor.class) Incoming HttpRequest Router (Directives) Pinpoint 
 AsyncContext AsyncContextAccessor 를 사용하여 AsyncContext 주입
  • 30. Akka HTTP Plugin 에서 비동기 처리 - RequestContext는 요청의 흐름을 타고 비동기로 호출되는 complete, failed 메소드로 전달 됨 - 이때 AsyncContext를 RequestContext 객체에서 가져오고 Trace를 종료 RequestContextImpl
 def complete() RequestContextImpl
 def failed() RequestContext Pinpoint 
 AsyncContext Trace 종료
  • 31. Akka HTTP Plugin 구현 - 비동기로 동작하는 Akka HTTP 의 트레이싱 결과 비동기 컨텍스트(AsyncContext)로 동작
  • 33. Welcome to the Scala Future 익명함수 익명함수 Future에 의한 비동기 호출 (Async stack trace) Future에 의한 비동기 호출 (Async stack trace) AsyncContext를 
 매번 전달해야됨
  • 34. Welcome to the Scala Future - 트레이싱이 필요한 수많은 로직들이 Scala Future API에 의해 비동기로 동작 - 익명함수로 호출되고 심지어는 인자를 
 전달하지 않기도 함 - AsyncContext를 전달하기가 굉장히 어렵기 에 비동기 Trace를 유지할 방법을 찾아야 함 익명함수 익명함수 Future에 의한 비동기 호출 (Async stack trace) Future에 의한 비동기 호출 (Async stack trace)
  • 35. Openwhisk 의 TransactionId 를 활용 - Openwhisk의 TransactionId는 요청 흐름을 추적하고 로깅을 수월하게 하기 위해 
 내부적으로 정의하여 사용되는 객체 - Scala의 암시적 파라미터(implicit parameter)를 통해 동기 또는 비동기적으로 호출되는 메소 드간에는 TransactionId 객체를 공유하며 컨텍스트를 유지 /** * Receives a message and runs the router. */ def route: Route = { assignId { implicit transid => respondWithHeader(transid.toHeader) { /** * Spawns a container in detached mode. * * @param image the image to start the container with * @param args arguments for the docker run command * @return id of the started container */ def run(image: String, args: Seq[String] = Seq.empty[String]) (implicit transid: TransactionId): Future[ContainerId] 요청의 처음 시작에서 
 TransactionId 객체가 만들어지고 할당됨
  • 36. TransactionId에 AsyncContext 주입 - AsyncContext는 Akka HTTP에서 만들어진 것을 사용 - Akka HTTP Plugin에서 시작된 AsyncContext를 통해 Trace를 지속할 수 있도록 RequestContext에 주입되어 있는 AsyncContext 를 다시 TransactionId 객체에 주입 TransactionId Pinpoint 
 AsyncContext RequestContext Pinpoint 
 AsyncContext Akka HTTP Plugin Openwhisk Plugin
  • 37. TransactionId에 AsyncContext 주입 - 이후 트레이싱이 필요한 메소드들은 암시적 파라미터(implicit parameter)로 전달받은 
 TransactionId의 AsyncContext 를 사용하여 AsyncTrace를 지속할 수 있음 TransactionId Openwhisk Plugin Pinpoint 
 AsyncContext /** * Spawns a container in detached mode. * * @param image the image to start the container with * @param args arguments for the docker run command * @return id of the started container */ def run(image: String, args: Seq[String] = Seq.empty[String]) (implicit transid: TransactionId): Future[ContainerId] 이 경우 플러그인에서 run 메소드를 
 Transform 하면 TransactionId 객체 접근 가능
  • 38. 그런데.. 몇 일 지나니 플러그인이 동작을 안한다? 힘들게 만들었는데..
  • 39. Openwhisk 는 incubating 프로젝트 - 아직까지 공식 릴리즈 버전이 없음 - 거의 매일 바뀌는 코드
 (하지만, 플러그인을 계속해서 수정할 수 없음) - => 대안이 필요
  • 40. 기존 Interceptor의 방식은? profiler.openwhisk.transform.targetname=org.apache.openwhisk.http.BasicHttpService. $anonfun$assignId$2 profiler.openwhisk.transform.targetparameter=org.apache.openwhisk.http.BasicHttpService, boolean,akka.http.scaladsl.server.RequestContext 1. 타겟 메소드를 설정에서 찾음 
 (메소드 이름과 파라미터) org.apache.openwhisk.http.BasicHttpService.$anonfun$assignId$2() { // method code } 2. BCI를 통해 타겟 메소드에 Interceptor를 주입함 3. Interceptor는 before, after 메소드에서 
 Trace 데이터를 기록함 Interceptor.before() Interceptor.after() * 변경 가능성이 있는 수많은 내부 메소드에 대해서 이 작업을 해야 함!
  • 41. 최소한의 메소드만 변형할수는 없을까? - Openwhisk는 내부적으로 로그를 출력하거나 메트릭을 수집할 때 특정 메소드의 실행 시간을 
 측정하기 위해 TransactionId 에 구현된 started(), finished() 메소드를 사용 중 메소드 시작 지점에 started 호출 종료 지점에 finished 호출
  • 42. started, finished 메소드를 Transform - 하나의 메소드에서 트레이싱이 이루어지는 
 기존의 방식을 두 개의 메소드로 분리 def started() { Interceptor.before() // something Interceptor.after() } def finished() { Interceptor.before() // something Interceptor.after() } 로직 실행 started 메소드가 호출되면 Interceptor 에서 Trace 시작 (일반적인 Interceptor와 다르게 Trace를 종료하지 않음) 이후 호출되는 finished 메소드에서 Trace 종료 (started 메소드에서 시작된 Trace를 종료함) Interceptor.before() Interceptor.before() Interceptor.after() Interceptor.after() def someMethod() { }
  • 43. started, finished 메소드를 Transform - 실제 메소드명이 아닌 started 메소드로 전달된 로그 마커를 메소드 이름으로 기록하고 
 로그 메시지는 새로운 marker.message annotation을 정의하고 기록 [2019-07-08T08:01:21.644Z] [INFO] [#tid_uZ9wiZOezssfabRZW2wcVPHxWqys2aF2] [ActionsApi] action action activation id: 81355efc90c847ddb55efc90c887dd74 [marker:controller_loadbalancer_start:8760]
  • 44. 이제는? - 어플리케이션에서 started, finished 메소드로 로그를 찍어주기만 하면 Pinpoint에서 Tracing 가능 - 플러그인 관리 주기가 길어짐 (최소 6개월 이상)
  • 45. 컴포넌트간의 메시지 전달하기 NGINX Controller Invoker CouchDB Invoker RestAPI + 인증 및 권한 컨테이너 구동, 함수 초기화 및 실행 액션 코드 및 실행 결과 저장
  • 46. 컴포넌트간의 메시지 전달하기 - Controller -> Invoker 컴포넌트간에는 ActivationMessage 객체를 주고 받음 - OpenTracing에서 사용하는 traceContext 필드에 플러그인에서 Pinpoint Transaction 정보 를 주입 Kafka에 메시지를 보내기 전에 traceContext를 조작
  • 47. 컴포넌트간의 메시지 전달하기 - Invoker는 ActivationMessage를 받으면 traceContext 필드에서 PinpointTransaction 정보 를 가지고 다시 Tracing을 시작 Invoker
  • 48. 다 잊어버리셔도 됩니다 ‣ Pinpoint agent 를 어플리케이션 실행 시 추가하면 바로 사용 가능 (핀포인트의 장점) ‣ -javaagent:${pinpointPath}/pinpoint-bootstrap-1.8.3.jar
 -Dpinpoint.applicationName=ApplicationName
 -Dpinpoint.agentId=AgentId 참 쉽죠..?
  • 50. 정리하면.. ‣ 핀포인트로 스칼라(Scala) 어플리케이션을 Tracing할 수 있습니다. ‣ 익명함수는 최대한 피하고.. 피할 수 없다면 설정으로 하는게 좋습니다.
 (더 좋은 방법이 있다면 알려주세요!) ‣ 비동기 호출을 요청하기 위해 AsyncContext를 전달 하는 방법을 먼저 찾아야 합니다. ‣ 코드 변경이 많은 프로젝트는.. 공통 인터페이스를 찾아 Transform 하면 좋습니다.