จัดการเส้นทางข้อมูลซับซ้อนและการรับมือข้อผิดพลาดอย่างมืออาชีพ
เรียนรู้การใช้ Enterprise Integration Patterns (EIPs) เช่น Splitter, Aggregator, Content-Based Router พร้อมระบบกู้คืนระบบล่ม (Resilient Routing & DLQ)
1. ทฤษฎีและสถาปัตยกรรม (Enterprise Integration Patterns)
รูปแบบมาตรฐานในการจัดเส้นทาง แปลง และกรองข้อมูลองค์กรตั้งแต่ปี 2007
1.1 EIP สำคัญที่ใช้งานบ่อยในระบบองค์กร
- Splitter Pattern: แยกแยะข้อมูล Collection หรือ JSON Array ขนาดใหญ่ ให้กลายเป็น Message รายย่อยทีละชิ้นเพื่อประมวลผลคู่ขนาน
- Aggregator Pattern: ทำงานตรงข้ามกับ Splitter โดยรวบรวม Message ย่อยหลาย ๆ ชิ้นกลับเป็นชุดเดียวกันตาม Correlation ID พร้อมกำหนดเงื่อนไขตัดรอบ (เช่น ครบ 100 รายการ)
- Content-Based Router (choice / when / otherwise): สวิตช์ตรวจสอบค่าใน Header หรือ Body แล้วส่งต่อไปยัง Endpoint ปลายทางที่ถูกต้อง
- Message Filter: กรองคัดเลือกเฉพาะ Message ที่ตรงตามเงื่อนไขให้ไหลผ่าน Route ต่อไป ส่วนที่ไม่ตรงจะถูกละทิ้ง
- Message Translator (Unmarshal / Marshal): แปลงโครงสร้างข้อมูลระหว่างระบบ เช่น แปลง JSON เป็น Object หรือ XML เป็น SQL
1.2 Error Handling & Resilient Routing
ระบบ Integration ที่ดีต้องมีความทนทานสูง (Resilient):
- Dead Letter Channel (DLC): เมื่อประมวลผลล้มเหลวและ Retry ครบโควตา จะย้ายข้อความเสียไปยัง Dead Letter Queue (DLQ) ทันที
- Redelivery Policy & Exponential Backoff: พยายามส่งซ้ำโดยเว้นระยะห่างทวีคูณ (เช่น 1s, 2s, 4s) เพื่อลดภาระระบบปลายทาง
- Circuit Breaker Pattern: ตัดการเชื่อมต่อชั่วคราวเมื่อปลายทางล่มบ่อย ป้องกันไม่ให้ปัญหารามลามทั้งระบบ (Cascading Failure)
1.3 แผนภาพจำลองการทำงาน EIP & Error Handling
ภาพจำลองการแยกข้อมูล Batch Orders และส่งเข้า DLQ เมื่อเกิดข้อผิดพลาด
เมื่อรับ Batch Orders เข้ามา ➔ ใช้ Splitter แตกรายการ ➔ ใช้ Content-Based Router แยกภูมิภาค (TH / Global) ➔ หากพังครบ 3 ครั้ง ส่งเข้า DLQ
📦
Batch Orders (Kafka)
➔ [Splitter] ➔
🔀
Content-Based Router
region == 'TH' ➔ DB_TH / Other ➔ DB_Global
➔ (Fail 3x) ➔
⚠️
Dead Letter Queue (DLQ)
2. ตัวอย่างโค้ดจริง (Java & YAML DSLs)
โจทย์: Split Batch Orders + Routing + Retry & DLQ
📁 OrderEipRoute.java
import org.apache.camel.builder.RouteBuilder;
public class OrderEipRoute extends RouteBuilder {
@Override
public void configure() throws Exception {
onException(Exception.class)
.maximumRedeliveries(3)
.redeliveryDelay(1000)
.backOffMultiplier(2)
.handled(true)
.to("kafka:orders-dlq");
from("kafka:batch-orders")
.split(body())
.choice()
.when(header("region").isEqualTo("TH"))
.to("sql:INSERT INTO orders_th (id, amount) VALUES (:#id, :#amount)")
.otherwise()
.to("sql:INSERT INTO orders_global (id, amount) VALUES (:#id, :#amount)")
.end();
}
}
🏋️♂️ โจทย์ฝึกปฏิบัติประจำวันที่ 2 (Hands-on Drill)
ฝึกออกแบบ Route ด้วยเงื่อนไขและระบบกู้คืนข้อผิดพลาด
- สร้าง Route รับข้อมูลจาก
kafka:transactions - ใช้ Message Filter คัดเลือกเฉพาะธุรกรรมที่มี
header.amount > 50000เท่านั้น - ตั้งค่า Redelivery Policy แบบ Retry 3 ครั้ง ครั้งละ 2 วินาที
- เมื่อ Retry ครบแล้วยังล้มเหลว ให้ย้ายข้อมูลไปเก็บที่
kafka:failed-transactions-dlq
📝 แบบทดสอบทบทวนบทเรียนวันที่ 2 (ตอบปุ๊บ รู้ผลปั๊บ)
เลือกคำตอบที่คุณคิดว่าถูกต้อง ระบบจะแสดงผลลัพธ์และคำอธิบายทันที