λ³Έ κΈμ λ§μ΄ν¬λ‘μλΉμ€μ λΆμ° μΆμ μ리μ¦λ‘ μ΄λ‘ κ³Ό μ€μ΅μ΄ ν¨κ» ν¬ν¨λ μ리μ¦μ λλ€. μλ λͺ©μ°¨μ νμλ κΈμ λͺ¨λ μ°Έκ³ νλ©΄ μ’μ΅λλ€.
λͺ©μ°¨
- Distributed Tracing, λΆμ° μΆμ μ΄λ?
- Spring Cloud Sleuth μ Zipkin
- Sleuth λ‘ Http νκ²½μ λΆμ° μΆμ μ€μ΅
- Sleuth λ‘ Messaging νκ²½μ λΆμ° μΆμ μ€μ΅
μ€μ΅μ λν μμ€μ½λλ₯Ό νμΈνμκ³ μΆλ€λ©΄ μ€μ΅ githubμμ νμΈνμ€ μ μμ΅λλ€.
Messaging νκ²½ μμμ λΆμ° μΆμ μ€μ΅
μ§λ μκ° μ°λ¦¬λ HTTP νκ²½μμμ λΆμ° μΆμ μ λν΄μ μμ보μλ€.
λ€μ νλ² κ°λ΅μ μΈ μν€ν μ²μ λν΄μ νμΈν΄λ³΄μ
μ μν€ν μ²λ₯Ό ꡬλΆνμλ©΄ 2κ°μ λΆλΆμΌλ‘ λλ μ μλ€.
- HTTP API
- Messaging
μ΄λ²μλ HTTP ν΅μ μ λμ΄ Messaging νκ²½μμ Span λ€μ νλμ Trace λ‘ κ΄λ¦¬ν μ μλλ‘ ν΄λ³Ό κ²μ΄λ€.
- user-service : express, node.js
- order-service : spring boot, java
- delivery-service : spring boot, java & aws sqs
- notification-service : spring boot, java & aws sqs
λ§μ΄ν¬λ‘μλΉμ€ νΈμΆ Flow
μ€μ΅μ λν νΈμΆμ flow λ₯Ό λΉμ¦λμ€μ μΈ ν λ¬Έμ₯μΌλ‘ νννμλ©΄ λ€μκ³Ό κ°λ€
μ¬μ©μ (User) κ° μ£Όλ¬Έ (Order) μ νλ€λ©΄ μ¬μ©μμ μ 보μ μ£Όλ¬Έ μνμ μ 보λ₯Ό ν λλ‘ λ°°μ‘ (Delivery) νκ³ , λ°°μ‘μ΄ μμλμλ€λ μλ¦Ό (Notification) μ μ μ‘νλ€.
μ κ³Όμ μ λ€μκ³Ό κ°μ νΈμΆμ΄ νλμ νΈλμμ μΌλ‘ μ΄λ£¨μ΄μ§λ€
- user-service λ order-service λ‘ HTTP GET μμ²μ 보λΈλ€
- order-service λ delivery-service λ‘ HTTP POST μμ²μ 보λΈλ€
- deliver-service λ HTTP μμ²μ΄ λ°μνλ©΄ AWS SQS λ‘ Message λ₯Ό produce νλ€.
- notification-service λ Queue μ λ©μμ§κ° μ‘΄μ¬νλ€λ©΄ Message λ₯Ό Consume νλ€
AWS SQS μ Queue λ§λ€κΈ°
μ°μ λ©μμ§ νκ²½μ ꡬννκΈ° μν΄μ AWS SQS μ ν νλλ₯Ό μμ±νμ
μ΄λ² μκ°μλ Message Queue λ AWS SQS μ λν μκ°μ΄ μλκΈ° λλ¬Έμ SQS κ΄λ ¨λ μ€μ μ λμ΄κ°λλ‘ νκ² λ€.
νκ° μ€λΉλμλ€λ©΄ μ΄μ Delivery Service μμ νμ μ°λμ ν΄λ³΄μ
Deliver-Service
deliver-service μμ λ€μκ³Ό κ°μ μμ‘΄μ±μ μΆκ°ν΄μ€λ€.
build.gradle
// zipkin & sleuth
implementation 'org.springframework.cloud:spring-cloud-starter-sleuth:3.1.1'
implementation 'org.springframework.cloud:spring-cloud-sleuth-zipkin:3.1.1'
implementation 'io.zipkin.aws:brave-instrumentation-aws-java-sdk-sqs:0.23.4'
// aws sqs
implementation 'org.springframework.cloud:spring-cloud-aws-messaging:2.2.6.RELEASE'
Zipkin κ³Ό Sleuth κ·Έλ¦¬κ³ Brave Instrumentation μ μΆκ°ν΄μ£Όλλ‘ νλ€
μ¬κΈ°μ λμ¬κ²¨ λ³Ό μ€μ μ λ°λ‘ λ€μ 2κ°μ΄λ€.
- org.springframework.cloud:spring-cloud-aws-messaging
- io.zipkin.aws:brave-instrumentation-aws-java-sdk-sqs:0.23.4
μ²μ²ν μ΄ν΄λ³΄μ
delivery-service μμ Producer μ€μ νκΈ°
Producer λ₯Ό μ€μ ν λ λ³΄ν΅ QueueMessagingTemplate μ μ¬μ©νκ³€ νλ€.
μ¬κΈ°μ Trace μ 보λ₯Ό μΆκ°νκΈ° μν΄μλ BraveInstrumentation μ SqsMessagingTemplate μ RequestHandler λ‘ μΆκ°ν΄μ€μΌ νλ€
@Configuration
public class SqsConfig {
Tracer tracer;
public SqsConfig(Tracer tracer) {
this.tracer = tracer;
}
@Bean
public QueueMessagingTemplate queueMessagingTemplate() {
Tracing current = Tracing.current();
SqsMessageTracing sqsMessageTracing = SqsMessageTracing.create(current);
AmazonSQSAsync client = AmazonSQSAsyncClientBuilder.standard()
.withRegion(Regions.AP_NORTHEAST_2)
.withCredentials(new EnvironmentVariableCredentialsProvider())
.withRequestHandlers(sqsMessageTracing.requestHandler())
.build();
return new QueueMessagingTemplate(client);
}
}
Brave Instrumentation μ΄λ Zipkin μλ²λ‘ Span λ°μ΄ν°λ₯Ό μ μ‘νλ ꡬν체μ΄λ€.
Messaging νκ²½μμλ B3-Propagation μ΄ μλνμ§ μλλ€.
Seamless ν Tracing νκ²½μ λ§λ€κΈ° μν΄μλ Queue λ‘ λμ§ Message μ Header μ B3 λ°μ΄ν°λ₯Ό λ£μ΄μ€μΌ νλ―λ‘ Tracer μ ꡬν체λ₯Ό μ§μ λ€λ€μΌ νλ€.
κ·Έ κ³Όμ μ΄ λ°λ‘ withRequestHandlers(sqsMessageTracing.requestHandler())
μ΄λ€
λ λμ¬κ²¨λ³Ό μ μ Tracing μ Bean μ£Όμ μ ν΅ν΄ κ°μ Έμ€λ κ²μ΄λ€.
Span μ λν Global ν Access λ₯Ό μν΄μλ μμ Zipkin & Sleuth λ₯Ό μ€λͺ νλ©° μ΄μΌκΈ°λ₯Ό μ μ νλ―, Bean μΌλ‘ μ£Όμ λ°μμΌ νλ€.
κ·ΈλμΌ Span μ λν Lifecycle μ λν κ΄λ¦¬κ° κ°λ₯νκ² λλ€.
MessageSender.java
μ΄μ Queue μ€μ μ΄ λλ¬μΌλ Queue μκ² Message λ₯Ό Send ν Sender λ₯Ό λ§λ€μ΄λ³΄μ
@Component
@RequiredArgsConstructor
public class MessageSender {
@Value("${aws.queue.name}")
private String notificationQueue;
private final QueueMessagingTemplate template;
public void send(Object message) {
template.convertAndSend(notificationQueue, message);
}
}
μΌλ°μ μΌλ‘ SQS Sender λ₯Ό ꡬνν λ μ¬μ©νλ λ°©μκ³Ό λμΌνλ€
κ·Έλ¦¬κ³ DeliveryController μ λ€μκ³Ό κ°μ΄ μμ²μ λ°μΌλ©΄ Message λ₯Ό Produce νλ λ‘μ§μ μΆκ°ν΄λ³΄μ
DeliveryController
@RestController
@RequestMapping("/delivery")
@RequiredArgsConstructor
public class DeliveryController {
private final MessageSender messageSender;
@PostMapping
public String delivery(@RequestBody DeliveryRequest request) {
String userId = request.getUserId();
String address = request.getAddress();
messageSender.send("λ°°μ‘ λ¬Έμ λ°μ‘ μμ²2");
return "[delivery-service] userId: " + userId + " address: " + address + " λ°°μ‘ μμ² μλ£";
}
}
μ΄μ λ€μ Zipkin Dashboard λ₯Ό νμΈν΄λ³΄μ
κ·ΈλΌ μμ κ°μ΄ message publish μ λν Span μ΄ μΆκ°λ κ²μ λ³Ό μ μλ€.
Messaging νκ²½μμλ HTTP νκ²½κ³Ό λ€λ₯΄κ² 2κ°μ§μ Annotation μ΄ μ‘΄μ¬νλ€.
- Producer Start
- Producer Finish
μ΄κ²μ 미루μ΄λ³΄μμ λ, Messaging νκ²½μμλ Span μ΄ Close λλ μμ , μ¦ Zipkin μΌλ‘ Reporting νλ μμ μ΄ Producer Finish νλ μμ μμ μ μ μλ€.
μ΄μ Consumer λ₯Ό λ§λ€μ΄λ³΄μ
Notification-Service
μ§κΈ ν΄λ³Ό λΆλΆμ Consumer μμ Consume ν Message λ₯Ό Trace νλ κ²μ΄λ€
μμ ν°μ μμμ ꡬννκΈ° μν΄μ Notification Service λ₯Ό λ§λ€μ΄λ³΄μ
μλλ₯Ό λ΄μ λΉ λ₯΄κ² μ½λλ§ μ°μ 보μ¬μ£Όλλ‘ νκ² λ€
SqsConfig.java
@Configuration
public class SqsConfig {
@Bean
public QueueMessagingTemplate queueMessagingTemplate() {
Tracing current = Tracing.current();
SqsMessageTracing sqsMessageTracing = SqsMessageTracing.create(current);
AmazonSQSAsync client = AmazonSQSAsyncClientBuilder.standard()
.withRegion(Regions.AP_NORTHEAST_2)
.withCredentials(new EnvironmentVariableCredentialsProvider())
.withRequestHandlers(sqsMessageTracing.requestHandler())
.build();
return new QueueMessagingTemplate(client);
}
}
SqsConfig μμλ Producer μ λ§μ°¬κ°μ§λ‘ QueueMessagingTemplate μ μμ±ν΄μ€ λ, Tracer λ₯Ό ν¨κ» λΆμ¬μΌνλ€
MessageReceiver.java
@Service
@RequiredArgsConstructor
public class MessageReceiver {
@SqsListener("${aws.queue.name}")
public void receiveMessage(String message) {
System.out.println("λ©μμ§ μμ μλ£, message = " + message);
}
}
MessageReceiver μμλ μΌλ²μ μΌλ‘ μ¬μ©νλ reveicer μ λκ°μ΄ ꡬνν΄μ£Όλ©΄ λλ€.
μ΄μ λͺ¨λ ꡬνμ΄ λλ¬κΈ° λλ¬Έμ μ 체μ μΈ μμ²μ λ€μ 보λ΄λ³΄λλ‘ νμ
νΉμλΌλ μμ΄λ²λ Έμ μ μμΌλ μ€μ΅μ λν νΈμΆμ flow λ₯Ό λΉμ¦λμ€μ μΈ ν λ¬Έμ₯μΌλ‘ ννν΄λ³΄μλ©΄,
μ¬μ©μ (User) κ° μ£Όλ¬Έ (Order) μ νλ€λ©΄ μ¬μ©μμ μ 보μ μ£Όλ¬Έ μνμ μ 보λ₯Ό ν λλ‘ λ°°μ‘ (Delivery) νκ³ , λ°°μ‘μ΄ μμλμλ€λ μλ¦Ό (Notification) μ μ μ‘νλ€.
μ΄κΈ° λλ¬Έμ User-Service λ‘ μμ²μ 보λ΄λ©΄ μ°λ¦¬μ Producer, Consumer λ€μ΄ μ λμν΄μ Zipkin Dashboard μ λμ°©ν κ²μ΄λ€
localhost:8000 μΈ user-service λ‘ μμ²μ 보λ΄λ©΄ λ€μκ³Ό κ°μ μ 보λ€μ΄ zipkin dashboard μ μ°νκ² λλ€.
λμΌλ‘..
μ΄λ κ² μ°λ¦¬λ κ°λ¨ν μ€μ΅μ κ±°μ³μ HTTP νκ²½κ³Ό Messaging νκ²½μμμ λ°μ΄ν°λ₯Ό Tracing ν΄λ³΄μλ€.
μμ¬μ΄ μ μ΄ μλ€λ©΄ μ΄λ€ λ°©μμΌλ‘ SpanId κ° μμ±λκ³ λμνλμ§μ λν΄μ κΉκ² μμλ³΄μ§ λͺ»νλ κ²μ΄ μμ½λ€.
νμ§λ§ λΆλͺ μ΄ λ€μ μκ° μΈμ κ°λ κ·Έ λΆλΆμ μ΄μΌκΈ°νλ μκ°μ΄ μμκ²μ΄λ€.
λκΈ