Error Channel
Error Channel์ ์ญํ
์ฅ์ ๊ฒฉ๋ฆฌ:
์ค๋ฅ๊ฐ ๋ฐ์ํ์ ๋ ์ ์ฒด ์์คํ ์ด ์ค๋จ๋๋ ๊ฒ์ ๋ฐฉ์งํ๊ณ , ๋ฌธ์ ๊ฐ ์๋ ๋ฉ์์ง๋ง ๋ถ๋ฆฌํ์ฌ ์ฒ๋ฆฌํฉ๋๋ค. ์ด๋ก ์ธํด ์ ์ฒด ์๋น์ค์ ๊ฐ์ฉ์ฑ๊ณผ ์์ ์ฑ์ด ํฅ์๋ฉ๋๋ค.
์ง๋จ ๋ฐ ๋๋ฒ๊น
:
์ค๋ฅ ํ ํฝ์ ์ ์ก๋ ๋ฉ์์ง๋ฅผ ๋ถ์ํ์ฌ ์ด๋ค ๋ฌธ์ ๊ฐ ๋ฐ์ํ๋์ง ์ฝ๊ฒ ํ์ ํ ์ ์์ต๋๋ค. ์ค๋ฅ ๋ฉํ๋ฐ์ดํฐ(์: ์ค๋ฅ ์์ธ, ์คํ ํธ๋ ์ด์ค)์ ํจ๊ป ์ ์ฅ๋๊ธฐ ๋๋ฌธ์ ๋ฌธ์ ์ ์์ธ์ ์ฐพ๋ ๋ฐ ๋์์ด ๋ฉ๋๋ค.
์ฌ์ฒ๋ฆฌ:
์ค๋ฅ์ ์์ธ์ ํด๊ฒฐํ ํ ์ค๋ฅ ํ ํฝ์ ์๋ ๋ฉ์์ง๋ฅผ ๋ค์ ์ฒ๋ฆฌํ ์ ์์ต๋๋ค. ์ด๋ฅผ ํตํด ์ผ์์ ์ธ ์ค๋ฅ๋ก ์ธํด ์คํจํ ๋ฉ์์ง๋ ๋์ค์ ์ฑ๊ณต์ ์ผ๋ก ์ฒ๋ฆฌ๋ ์ ์์ต๋๋ค.
๋ชจ๋ํฐ๋ง ๋ฐ ์๋ฆผ:
Error Channel์ ๋ชจ๋ํฐ๋งํ์ฌ ์ค๋ฅ ๋ฐ์ ๋น์จ์ด๋ ํน์ ์๊ณ๊ฐ์ ์ด๊ณผํ๋ ๊ฒฝ์ฐ ์๋ฆผ์ ๋ฐ์ ์ ์์ต๋๋ค. ์ด๋ฅผ ํตํด ์์คํ ์ ๊ฑด๊ฐ ์ํ๋ฅผ ์ง์์ ์ผ๋ก ํ์ธํ๊ณ ํ์ํ ์กฐ์น๋ฅผ ์ทจํ ์ ์์ต๋๋ค.
์์คํ
๋ณต์๋ ฅ ํฅ์:
Error Channel์ ํ์ฉํ๋ฉด ์์คํ ์ ์์์น ๋ชปํ ์ค๋ฅ์ ๋ํด ๋์ฑ ํ๋ ฅ์ ์ผ๋ก ๋์ํ ์ ์์ต๋๋ค. ์ค๋ฅ ๋ฐ์ ์ ํด๋น ๋ฉ์์ง๋ง ๋ฐ๋ก ์ฒ๋ฆฌํ๊ณ , ์ ์ ๋ฉ์์ง๋ ๊ณ์ ์ฒ๋ฆฌ๋ ์ ์๊ธฐ ๋๋ฌธ์ ๋๋ค
When user Error Channel ?
์ฌ์ฒ๋ฆฌ๊ฐ ํ์ํ ๊ฒฝ์ฐ
์์: ์ธ๋ถ ๊ฒฐ์ ์๋น์ค ํธ์ถ
E-commerce ์์คํ ์์๋ ์ฃผ๋ฌธ ๋ฉ์์ง๋ฅผ ์ฒ๋ฆฌํ ๋ ์ธ๋ถ์ ๊ฒฐ์ ์๋น์ค๋ฅผ ํธ์ถํฉ๋๋ค. ์ด ์ธ๋ถ ์๋น์ค๋ ๋๋๋ก ์ผ์์ ์ธ ์ค๋ฅ๋ฅผ ๋ฐํํ ์ ์์ต๋๋ค.
public class TemporaryPaymentException extends RuntimeException {
public TemporaryPaymentException(String message) {
super(message);
}
}
@KafkaListener(topics = "order-topic")
public void processOrder(String order) {
try {
// ... ์ฃผ๋ฌธ ๋ก์ง ...
paymentService.charge(order);
} catch (TemporaryPaymentException e) {
// ์ผ์์ ์ธ ๊ฒฐ์ ์ค๋ฅ: Error Channel๋ก ์ ์กํ์ฌ ๋์ค์ ์ฌ์ฒ๋ฆฌ
errorKafkaTemplate.send("payment-retry-topic", order);
}
}
๋ถ์์ด ํ์ํ ๊ฒฝ์ฐ
์์: ์ ํจํ์ง ์์ ์ฃผ๋ฌธ ํ์
์ฃผ๋ฌธ ๋ฉ์์ง์ ํ์์ด ์ ํจํ์ง ์๊ฑฐ๋ ์์์น ๋ชปํ ํ๋๋ฅผ ํฌํจํ๊ณ ์๋ ๊ฒฝ์ฐ.
public class InvalidOrderFormatException extends RuntimeException {
public InvalidOrderFormatException(String message) {
super(message);
}
}
@KafkaListener(topics = "order-topic")
public void processOrder(String order) {
try {
// ... ์ฃผ๋ฌธ ๋ก์ง ...
orderValidator.validate(order);
} catch (InvalidOrderFormatException e) {
// ์ ํจํ์ง ์์ ์ฃผ๋ฌธ ํ์: Error Channel๋ก ์ ์กํ์ฌ ๋ถ์์ ์ํ ์ ์ฅ
errorKafkaTemplate.send("invalid-order-format-topic", order);
}
}
ํน๋ณํ ๋์์ด ํ์ํ ๊ฒฝ์ฐ
์์: ํฐ ๊ธ์ก์ ์ฃผ๋ฌธ ๊ฑฐ์
์์ ์ ์ผ์ ๊ธ์ก ์ด์์ ์ฃผ๋ฌธ์ ๋ํด ์ถ๊ฐ ๊ฒํ ๊ฐ ํ์ํฉ๋๋ค. ์ด๋ฐ ์ฃผ๋ฌธ๋ค์ ์๋์ผ๋ก ๊ฑฐ์ ๋๊ณ ๊ด๋ฆฌ์์๊ฒ ์๋ฆผ์ด ์ ์ก๋ฉ๋๋ค.
public class LargeOrderException extends RuntimeException {
public LargeOrderException(String message) {
super(message);
}
}
@KafkaListener(topics = "order-topic")
public void processOrder(String order) {
try {
// ... ์ฃผ๋ฌธ ๋ก์ง ...
if (orderService.isLargeOrder(order)) {
throw new LargeOrderException("Order amount exceeds the limit");
}
} catch (LargeOrderException e) {
// ํฐ ๊ธ์ก์ ์ฃผ๋ฌธ ๊ฑฐ์ : Error Channel๋ก ์ ์กํ๊ณ ๊ด๋ฆฌ์์๊ฒ ์๋ฆผ
errorKafkaTemplate.send("large-order-topic", order);
notificationService.notifyAdmin(e.getMessage());
}
}
์ฌ์ฒ๋ฆฌ ๋ฐฉ๋ฒ
์๋ ์ฌ์ฒ๋ฆฌ:
๊ด๋ฆฌ์ ๋๋ ์ฐ์ฐ์๊ฐ ํน์ ํด ๋๋ ์ธํฐํ์ด์ค๋ฅผ ์ฌ์ฉํ์ฌ ์ค๋ฅ ๋ฉ์์ง๋ฅผ ๊ฒํ ํ๊ณ ์๋์ผ๋ก ์ฌ์ฒ๋ฆฌ๋ฅผ ๊ฒฐ์ ํ ์ ์์ต๋๋ค.
์๋ ์ฌ์๋:
Kafka ๊ฐ์ ๋ฉ์์ง ์์คํ ์ ๋ฉ์์ง ์๋น ์คํจ์ ์ฌ์๋ ๋ฉ์ปค๋์ฆ์ ์์ฒด์ ์ผ๋ก ์ ๊ณตํ ์ ์์ต๋๋ค. ์ด๋ฌํ ์ค์ ์ Kafka consumer์ ์ค์ ์ ํตํด ์กฐ์ ํ ์ ์์ต๋๋ค. ์ฌ์๋ ํ์, ์ฌ์๋ ๊ฐ๊ฒฉ ๋ฑ์ ์ค์ ํ์ฌ ์๋์ผ๋ก ๋ฉ์์ง๋ฅผ ์ฌ์ฒ๋ฆฌํ๋๋ก ํ ์ ์์ต๋๋ค.
์ค์ผ์ฅด๋ง๋ ์ฌ์ฒ๋ฆฌ:
"payment-retry-topic"์ ๊ฐ์ ํน์ ์ฌ์๋ ํ ํฝ์ ๋ฉ์์ง๋ฅผ ๋ณด๋ด๋ ๊ฒ ์ธ์๋, ์ค์ผ์ฅด๋ง๋ ์์ (์: Spring Scheduled Task, Quartz Scheduler ๋ฑ)์ ์ฌ์ฉํ์ฌ ์ ๊ธฐ์ ์ผ๋ก ์ด ํ ํฝ์ ํด๋งํ๊ณ ์ฌ์ฒ๋ฆฌํ ๋ฉ์์ง๊ฐ ์๋์ง ํ์ธํ๊ณ ์ฒ๋ฆฌํ ์ ์์ต๋๋ค.
Dead Letter Queue (DLQ):
์ฌ์๋ ํ์๊ฐ ํน์ ํ์๋ฅผ ์ด๊ณผํ ๊ฒฝ์ฐ ๋ฉ์์ง๋ฅผ Dead Letter Queue(DLQ)๋ผ๋ ๋ณ๋์ ํ ํฝ์ผ๋ก ์ ์กํ ์ ์์ต๋๋ค. DLQ์ ์๋ ๋ฉ์์ง๋ ์๋์ผ๋ก ๊ฒํ ๋๊ณ , ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ํ ์ฌ์ฒ๋ฆฌ๋ ์ ์์ต๋๋ค.
Last updated
Was this helpful?