ภาพรวม เรียนรู้วิธีการทําให้การโทร microservice ของคุณทนทานโดยใช้แบบ Circuit Breaker ด้วย และ — การแสดงตัวอย่างที่สมบูรณ์คําสั่งขั้นตอนตามขั้นตอนคําอธิบายชั้นตามชั้นการผลิตตัวอย่างกรณีการใช้งานในโลกจริงและเคล็ดลับการผลิต Resilience4j Spring Boot Why This Matters ทําไมสิ่งนี้สําคัญ ในระบบกระจายตัวบริการล้มเหลวด้านล่างสามารถกระโดดและทําให้เกิดการหยุดทํางานของระบบโดยรวม รูปแบบ : Circuit Breaker ตรวจสอบความเสี่ยงที่ล้มเหลว หยุดการส่งคําขอไปยังมัน (เพื่อหลีกเลี่ยงการเสียทรัพยากร) กลับกลับการตอบสนองการล้มเหลวที่สง่างาม ตรวจสอบระยะเวลาการติดยาเสพติดและฟื้นฟูการทํางานปกติเมื่อมีสุขภาพดี นี้ลดเวลาหยุดทํางานปกป้องสระว่ายน้ําลวดรักษาประสบการณ์ของผู้ใช้ที่เหมาะสมและป้องกันฝนตกใหม่ Demo Summary (What You Have) Demo Summary (สิ่งที่คุณมี) สองบริการ Maven demo: (port ) — simple REST provider that intentionally fails intermittently. hello-service 8081 จุดสิ้นสุด GET /api/hello (port ) — calls hello-service using RestTemplate and is protected by with a fallback. client-service 8080 Resilience4j @CircuitBreaker จุดสิ้นสุด GET /api/get-message เก็บทั้งสอง ( ) hello-service and client-service การทดสอบ GET http://localhost:8080/api/get-message แผนภาพสถาปัตยกรรม นี่คือการไหลขนาดเล็กที่มุ่งเน้นเหมาะสําหรับการวาดแผนภูมิ Files & Code: Class-By-Class Explanation ไฟล์และรหัส: Class-by-Class คําอธิบาย hello-service HelloServiceApplication.java Standard bootstrap class. @SpringBootApplication HelloController.java @RestController public class HelloController { private static int counter = 0; @GetMapping("/api/hello") public String sayHello() { counter++; // simulate intermittent failure: fail on every 3rd request if (counter % 3 == 0) { throw new RuntimeException("Simulated failure from Hello-Service!"); } return "Hello from Hello-Service! (count=" + counter + ")"; } } ตัวควบคุมนี้มุ่งเน้นไปที่ RuntimeException บนการโทรเป็นประจําเพื่อจําลองความล้มเหลวชั่วคราวที่คุณจะเห็นในระบบจริง (ความล้มเหลวของ DB, ข้อมูลที่ไม่ดี, เวลาหมดอายุ) Explanation: client-service ลูกค้าบริการแอปพลิเคชัน.java มาตรฐาน Spring Boot ชั้นหลัก ไม่จําเป็นต้องมีการกําหนดค่าพิเศษ AppConfig.java @Configuration public class AppConfig { @Bean public RestTemplate restTemplate() { return new RestTemplate(); } } ให้ตัวอักษร RestTemplate เดียว ให้ตัวอักษร RestTemplate เป็นตัวอักษร Spring เพื่อให้ตัวอักษร AOP / Resilience สามารถทํางานได้อย่างถูกต้อง Explanation: HelloClientService.java @Service public class HelloClientService { private final RestTemplate restTemplate; @Value("${hello.service.url}") private String helloServiceUrl; public HelloClientService(RestTemplate restTemplate) { this.restTemplate = restTemplate; } @CircuitBreaker(name = "helloService", fallbackMethod = "fallbackHello") public String getHelloMessage() { System.out.println("Calling hello service: " + helloServiceUrl); return restTemplate.getForObject(helloServiceUrl, String.class); } public String fallbackHello(Throwable t) { System.out.println("Fallback triggered: " + t); return "Hello Service is currently unavailable. Please try again later."; } } Explanation (crucial bits) @CircuitBreaker(name = "helloService", fallbackMethod = "fallbackHello") wraps the getHelloMessage() call in a circuit breaker. The name links to configuration properties. fallbackHello(Throwable t) is called when the call fails according to the breaker rules. The fallback must: o Be in the same class o Have the same return type o Accept the original method parameters (none here) and a final Throwable parameter (or Exception/Throwable compatible with thrown exceptions) Important: The method must be public, and the class must be a Spring bean (@Service), so proxy-based AOP works. ClientController.java @RestController public class ClientController { private final HelloClientService helloClientService; public ClientController(HelloClientService helloClientService) { this.helloClientService = helloClientService; } @GetMapping("/api/get-message") public String getMessage() { return helloClientService.getHelloMessage(); } } ตัวควบคุมง่ายๆที่ส่งมอบให้ สิ่งนี้ช่วยให้แน่ใจว่าการโทรผ่านโปรกซีที่ถูกนํามาใช้ Explanation: HelloClientService Configuration Used (client-service application.properties) การกําหนดค่าที่ใช้ (client-service application.properties) การกําหนดค่าที่สําคัญที่ใช้ใน demo server.port=8080 spring.application.name=client-service hello.service.url=http://localhost:8081/api/hello resilience4j.circuitbreaker.instances.helloService.registerHealthIndicator=true resilience4j.circuitbreaker.instances.helloService.slidingWindowSize=5 resilience4j.circuitbreaker.instances.helloService.minimumNumberOfCalls=2 resilience4j.circuitbreaker.instances.helloService.failureRateThreshold=50 resilience4j.circuitbreaker.instances.helloService.waitDurationInOpenState=10s logging.level.io.github.resilience4j.circuitbreaker=DEBUG Meaning of important properties slidingWindowSize: จํานวนการโทรที่สวิทช์สวิทช์สําหรับเปอร์เซ็นต์ความล้มเหลว minimumNumberOfCalls: การโทรขั้นต่ําก่อนที่อัตราความล้มเหลวจะถูกประเมิน faultRateThreshold: เปอร์เซ็นต์ของความล้มเหลว (เช่น 50) เพื่อเปิดวงจร waitDurationInOpenState: ระยะเวลาที่วงจรยังคงเปิดก่อนที่จะเปลี่ยนเป็นครึ่งเปิด registerHealthIndicator: แสดงสถานะเบรกเกอร์ผ่านตัวกระตุ้น ขั้นตอนตามขั้นตอนและผลลัพธ์ที่คาดหวัง เริ่มบริการ เริ่มบริการ Hello-Service Visit: http://localhost:8081/api/hello → "Hello from Hello-Service!" (หรือโยนการล้มเหลวแบบจําลอง) Returns เริ่มบริการลูกค้า Visit: http://localhost:8080/api/get-message Test Scenarios & Outputs การทดสอบสถานการณ์ & Outputs Scenario A — Hello-Service Healthy ส่งคําขอ GET http://localhost:8080/api/get-message ลูกค้าบันทึก Calling hello service: http://localhost:8081/api/hello 2025-11-13T11:58:23.366+05:30 DEBUG 32692 --- [client-service] [nio-8080-exec-8] i.g.r.c.i.CircuitBreakerStateMachine : CircuitBreaker 'helloService' succeeded: 2025-11-13T11:58:23.366+05:30 DEBUG 32692 --- [client-service] [nio-8080-exec-8] i.g.r.c.i.CircuitBreakerStateMachine : Event SUCCESS published: 2025-11-13T11:58:23.366634+05:30[Asia/Calcutta]: CircuitBreaker 'helloService' recorded a successful call. Elapsed time: 15 ms Response Hello from Hello-Service! (count=4) Scenario B — Hello-Service Intermittent Failures หากคุณเรียกซ้ําและโยน Hello-Service สําหรับคําขอบางอย่าง: RuntimeException ●การโทรที่ประสบความสําเร็จ: ลูกค้าจะกลับข้อความ Hello ●เมื่อการโทรแบบดาวน์โหลดกลับ HTTP 500 / exception: o Resilience4j records the failure. o If failure rate exceeds threshold (e.g., 50% over sliding window), the Circuit becomes **OPEN**. o While OPEN, calls are short-circuited; **fallbackHello**() is immediately executed — no network call. \n **Client response while fallback active** Client Response while active Response Hello Service is currently unavailable. Please try again later. Sample client log sequence Calling hello service: http://localhost:8081/api/hello 2025-11-13T12:00:55.842+05:30 DEBUG 32692 --- [client-service] [nio-8080-exec-1] i.g.r.c.i.CircuitBreakerStateMachine : CircuitBreaker 'helloService' recorded an exception as failure: Scenario C — Recovery หลังจาก ระยะเวลาการเปิดตัว (10s) ระยะเวลาการเปิดตัว Circuit ไปยัง HALF_OPEN: การโทรทดสอบเพียงไม่กี่ครั้งจะได้รับอนุญาต หากการโทรทดสอบประสบความสําเร็จสวิทช์จะปิดและการจราจรปกติจะกลับมา หากการทดสอบล้มเหลวสวิทช์จะกลับไปที่ Open Real-World Use Cases กรณีการใช้งานในโลกจริง การบูรณาการการชําระเงิน - บริการเช็คเอาท์ที่เรียกร้อง API ของธนาคารภายนอก: หาก API ของธนาคารช้า / ล้มเหลวเครื่องตัดวงจรจะกลับข้อความที่เป็นมิตรกับผู้ใช้และป้องกันไม่ให้เกิดฝนตก API ที่ จํากัด อัตราของบุคคลที่สาม - API ที่ จํากัด การโทรต่อวินาที - เมื่อบรรลุขีด จํากัด วงจรจะเปิดเพื่อหลีกเลี่ยงการโจมตีอัตราเพิ่มเติม; fallback กลับข้อมูลที่เก็บไว้ใน cache เครือข่ายไมโครบริการภายในองค์กร - บริการ A โทรหา B ซึ่งโทรหา C. หาก C ไม่เสถียรสวิตช์เปิดป้องกัน B และ A ป้องกันการชะลอตัวทั่วระบบ การสลับคุณสมบัติและการลดลงอย่างมีเสน่ห์ - เมื่อบริการคุณสมบัติที่ไม่สําคัญล้มเหลวให้กลับผลลัพธ์ที่ง่ายขึ้นเพื่อให้ฟังก์ชั่นหลักสามารถใช้งานได้ (เช่นการกลับรายการผลิตภัณฑ์โดยไม่มีคําแนะนํา) Advantages & Business Value ข้อได้เปรียบและมูลค่าธุรกิจ การแยกข้อบกพร่อง - ป้องกันการติดยาเสพติดที่ไม่ดีหนึ่งจากการตกตะกอน การตอบสนองความล้มเหลวที่เร็วขึ้น - ล้มเหลวอย่างรวดเร็วแทนที่จะรอเวลา การลดลงที่พึงประสงค์ - ให้การตอบสนองกลับแทนการหยุดทํางานอย่างสมบูรณ์ การป้องกันทรัพยากร - หลีกเลี่ยงการสูญเสีย CPU, threads และเครือข่าย การกู้คืนอัตโนมัติ - โดยอัตโนมัติกลับไปปกติเมื่อความเสพติดเป็นสุขภาพดี ความสามารถในการสังเกต - สถานะและเมตริกเกอร์สามารถเปิดเผยผ่านทาง Actuator และตรวจสอบได้ Sample logs you’ll see (realistic) Calling hello service: http://localhost:8081/api/hello 2025-11-13T12:00:55.842+05:30 DEBUG 32692 --- [client-service] [nio-8080-exec-1] i.g.r.c.i.CircuitBreakerStateMachine : CircuitBreaker 'helloService' recorded an exception as failure 2025-11-13T12:00:55.847+05:30 DEBUG 32692 --- [client-service] [nio-8080-exec-1] i.g.r.c.i.CircuitBreakerStateMachine : Event ERROR published: 2025-11-13T12:00:55.847908200+05:30[Asia/Calcutta]: CircuitBreaker 'helloService' recorded an error: 'org.springframework.web.client.HttpServerErrorException$InternalServerError: 500 : "{"timestamp":"2025-11-13T06:30:55.842+00:00","status":500,"error":"Internal Server Error","path":"/api/hello"}"'. Elapsed time: 8 ms Fallback triggered: org.springframework.web.client.HttpServerErrorException$InternalServerError: 500 : "{"timestamp":"2025-11-13T06:30:55.842+00:00","status":500,"error":"Internal Server Error","path":"/api/hello"}"