-
Notifications
You must be signed in to change notification settings - Fork 0
Fix: 서킷브레이커 패널 표시 오류 수정 #113
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -14,6 +14,8 @@ | |||||||||||||||||||||||
| import org.springframework.kafka.core.*; | ||||||||||||||||||||||||
| import org.springframework.kafka.listener.DeadLetterPublishingRecoverer; | ||||||||||||||||||||||||
| import org.springframework.kafka.listener.DefaultErrorHandler; | ||||||||||||||||||||||||
| import org.springframework.kafka.support.serializer.ErrorHandlingDeserializer; | ||||||||||||||||||||||||
| import org.springframework.kafka.support.serializer.JsonDeserializer; | ||||||||||||||||||||||||
| import org.springframework.util.backoff.FixedBackOff; | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| import java.util.HashMap; | ||||||||||||||||||||||||
|
|
@@ -70,10 +72,19 @@ public ConsumerFactory<String, Object> consumerFactory() { | |||||||||||||||||||||||
| config.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapServers); | ||||||||||||||||||||||||
| config.put(ConsumerConfig.GROUP_ID_CONFIG, "catchtable-notification-group"); | ||||||||||||||||||||||||
| config.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest"); | ||||||||||||||||||||||||
| config.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class); | ||||||||||||||||||||||||
| config.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, "org.springframework.kafka.support.serializer.JsonDeserializer"); | ||||||||||||||||||||||||
| config.put("spring.json.trusted.packages", "com.catchtable.notification.event,java.lang.String,java.lang.Object"); | ||||||||||||||||||||||||
| config.put("spring.json.use.type.headers", true); | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| // ErrorHandlingDeserializer 로 감싸 deserialize 실패 시 SerializationException 을 발생시키지 않고 | ||||||||||||||||||||||||
| // null payload + 헤더에 실패 정보를 담아 record 를 통과시킨다. DefaultErrorHandler 가 그 record 를 | ||||||||||||||||||||||||
| // recoverer(DLT publish) 로 넘기고 다음 메시지로 진행하므로 잘못된 메시지 1건이 consumer 를 | ||||||||||||||||||||||||
| // 영구 stuck 시키는 문제가 해소된다. | ||||||||||||||||||||||||
| config.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, ErrorHandlingDeserializer.class); | ||||||||||||||||||||||||
| config.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, ErrorHandlingDeserializer.class); | ||||||||||||||||||||||||
| config.put(ErrorHandlingDeserializer.KEY_DESERIALIZER_CLASS, StringDeserializer.class.getName()); | ||||||||||||||||||||||||
| config.put(ErrorHandlingDeserializer.VALUE_DESERIALIZER_CLASS, JsonDeserializer.class.getName()); | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| config.put(JsonDeserializer.TRUSTED_PACKAGES, "com.catchtable.notification.event,java.lang.String,java.lang.Object"); | ||||||||||||||||||||||||
| // 헤더 미포함 메시지(외부 시스템/CLI) 대비 fallback. 헤더가 있으면 우선 적용된다. | ||||||||||||||||||||||||
| config.put(JsonDeserializer.USE_TYPE_INFO_HEADERS, true); | ||||||||||||||||||||||||
|
Comment on lines
+80
to
+87
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 헤더 미포함 메시지 처리를 위한
|
||||||||||||||||||||||||
| config.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, ErrorHandlingDeserializer.class); | |
| config.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, ErrorHandlingDeserializer.class); | |
| config.put(ErrorHandlingDeserializer.KEY_DESERIALIZER_CLASS, StringDeserializer.class.getName()); | |
| config.put(ErrorHandlingDeserializer.VALUE_DESERIALIZER_CLASS, JsonDeserializer.class.getName()); | |
| config.put(JsonDeserializer.TRUSTED_PACKAGES, "com.catchtable.notification.event,java.lang.String,java.lang.Object"); | |
| // 헤더 미포함 메시지(외부 시스템/CLI) 대비 fallback. 헤더가 있으면 우선 적용된다. | |
| config.put(JsonDeserializer.USE_TYPE_INFO_HEADERS, true); | |
| config.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class); | |
| config.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, ErrorHandlingDeserializer.class); | |
| config.put(ErrorHandlingDeserializer.VALUE_DESERIALIZER_CLASS, StringDeserializer.class.getName()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
forced_open및disabled상태 누락으로 인한 오탐지 위험현재 PromQL 식은
closed(0),half_open(1),open(2) 상태만 고려하여 합산하고 있습니다.하지만 Resilience4j에는
forced_open및disabled상태도 존재합니다. 만약 운영 중에 긴급 대응이나 테스트를 위해 서킷 브레이커를forced_open상태로 강제 전환할 경우,closed/half_open/open메트릭은 모두0이 되고forced_open메트릭만1이 됩니다.이 경우 현재 식의 결과는
0이 되어 대시보드에는 정상 상태인CLOSED(초록색)로 표시되는 오탐지(Misleading)가 발생할 수 있습니다.따라서
forced_open상태도open과 동일하게2로 매핑할 수 있도록 정규식(=~"open|forced_open")을 사용하는 것을 권장합니다.