
การทำ Rate Limiting และ Circuit Breaker
(Resilience4J กับ WebFlux)
20-minute read • Updated 19 July 2025
สารบัญ
- เกริ่นนำ
- ทำความเข้าใจแนวคิด
- สแตกเทคโนโลยี & Blueprint
- เตรียมโปรเจค & Dependency
- ตั้งค่า Rate Limiter & Circuit Breaker (application.yml)
- ตัวอย่าง Service แบบ Reactive
- ผสานกับ Router Functions
- Monitoring & Dashboards
- Rate Limiter vs Circuit Breaker
- Best Practices
- Testing & Tuning
- สรุป
1. เกริ่นนำ
ระบบ Microservices ที่รับ ทราฟฟิกสูง ต้องเผชิญสองปัญหาหลักคือ การป้องกันการโจมตีแบบ DoS/Brute force และ การล่มพังแบบทอด Domino ของบริการ downstream เมื่อเกิด failure สะสม Rate Limiting และ Circuit Breaker เป็นคู่หูหลักในการเพิ่ม MTBF และลด MTTR ของระบบ Reactive API ที่เราเขียนด้วย Spring WebFlux
2. ทำความเข้าใจแนวคิด

2.1 Rate Limiting
กลไกที่ “เคาะประตู” ทุกครั้งก่อนเข้า API เพื่อเช็กว่าจำนวน token หรือ permit ใน bucket ยังเหลือหรือไม่ ถ้าเกิน ระบบตอบ HTTP 429 Too Many Requests
ประโยชน์คือ กันล้น (throttling) และ กันเจตนาร้าย เช่น Brute Force Login
2.2 Circuit Breaker

ทำหน้าที่เปรียบเสมือน “Fuse” ตัดวงจรเมื่อ downstream ล้มเหลวเกินเกณฑ์ ป้องกัน Thread Exhaustion และช่วยระบบฟื้นตัวได้เร็ว
3. สแตกเทคโนโลยี & Blueprint
- Spring Boot 3.5.x + Spring WebFlux (Reactive stack)
- Resilience4J 2.2.x (RateLimiter, CircuitBreaker, Retry, Bulkhead)
- Micrometer + Prometheus + Grafana (Metrics & Dashboard)
- ตัวอย่าง build ด้วย Maven แต่ปรับเป็น Gradle ได้เช่นกัน
4. เตรียมโปรเจค & Dependency
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-webflux</artifactId> </dependency> <dependency> <groupId>io.github.resilience4j</groupId> <artifactId>resilience4j-spring-boot3</artifactId> </dependency> <dependency> <groupId>io.github.resilience4j</groupId> <artifactId>resilience4j-reactor</artifactId> </dependency> <dependency> <groupId>io.micrometer</groupId> <artifactId>micrometer-registry-prometheus</artifactId> </dependency>
5. ตั้งค่า Rate Limiter & Circuit Breaker (application.yml)
resilience4j: ratelimiter: instances: bookingService: limitForPeriod: 50 limitRefreshPeriod: 1s timeoutDuration: 0 circuitbreaker: instances: bookingService: slidingWindowType: COUNT_BASED slidingWindowSize: 100 failureRateThreshold: 50 waitDurationInOpenState: 20s slowCallDurationThreshold: 2s slowCallRateThreshold: 50 management: endpoints: web: exposure: include: health,info,prometheus
6. ตัวอย่าง Service แบบ Reactive
@Service @RequiredArgsConstructor public class BookingService { private final WebClient backendClient; private final RateLimiter bookRateLimiter = RateLimiter.ofDefaults("bookingService"); private final CircuitBreaker bookCircuitBreaker = CircuitBreaker.ofDefaults("bookingService"); public Mono<BookingDto> createBooking(Mono<RequestDto> req) { return req.flatMap(r -> backendClient.post() .uri("/backend/book") .bodyValue(r) .retrieve() .bodyToMono(BookingDto.class)) .transformDeferred(RateLimiterOperator.of(bookRateLimiter)) .transformDeferred(CircuitBreakerOperator.of(bookCircuitBreaker)); } }
7. ผสานกับ Router Functions
@Bean RouterFunction<ServerResponse> routes(BookingHandler handler) { return RouterFunctions.route() .POST("/api/book", handler::create) .build(); } @Component @RequiredArgsConstructor class BookingHandler { private final BookingService service; Mono<ServerResponse> create(ServerRequest r) { return service.createBooking(r.bodyToMono(RequestDto.class)) .flatMap(b -> ServerResponse.ok().bodyValue(b)) .onErrorResume(CallNotPermittedException.class, ex -> ServerResponse.status(503).build()) .onErrorResume(RequestNotPermitted.class, ex -> ServerResponse.status(429).build()); } }
8. Monitoring & Dashboards
Resilience4J ส่งเมตริกผ่าน Micrometer: resilience4j_circuitbreaker_state
, resilience4j_ratelimiter_available_permissions
ฯลฯ
ต่อ Prometheus แล้วสร้าง Grafana Board ภาพรวมสุขภาพบริการได้ทันที
9. Rate Limiter vs Circuit Breaker

ทั้งสอง pattern ป้องกัน overload เหมือนกันแต่ใช้ “เวลาที่ต่างกัน”
- Rate Limiter → ป้องกันก่อนเกิดปัญหา (Pre-Control)
- Circuit Breaker → ตัดวงจรหลังพบ error (Post-Control)
10. Best Practices
- ใช้ different instance name ต่อ service เพื่อแยกสถิติแม่นยำ
- เก็บค่าใน Central Config แล้วรีโหลดผ่าน Spring Cloud Config
- ตั้ง timeoutDuration เป็น 0 สำหรับ reactive เพื่อไม่ block
- ใช้ Fallback แบบ cache/queue เพื่อรักษา UX
11. Testing & Tuning
@Test void shouldOpenCircuitWhenFailure() { CircuitBreaker cb = CircuitBreaker.of("test", CircuitBreakerConfig.custom() .failureRateThreshold(50) .slidingWindowSize(2) .waitDurationInOpenState(Duration.ofSeconds(1)) .build()); Flux.error(new IllegalStateException()) .transformDeferred(CircuitBreakerOperator.of(cb)) .onErrorResume(e -> Mono.empty()) .repeat(2) .blockLast(); assertEquals(CircuitBreaker.State.OPEN, cb.getState()); }
12. สรุป
เพียงไม่กี่บรรทัด คุณก็เพิ่ม Rate Limiter และ Circuit Breaker ให้กับ API WebFlux ได้แล้ว Resilience4J ช่วยให้ปรับแต่งง่าย เห็นผลลัพธ์ผ่าน Metrics ทันที เมื่อเลือกค่า threshold เหมาะสม ระบบของคุณจะ เสถียร ปลอดภัย และ รองรับทราฟฟิกมหาศาล พร้อมลุย production!
พร้อมทดลอง? ลอง Fork โค้ดตัวอย่าง repo นี้ แล้วลุยเลย ✌️
© 2025 poolsawat.com • หากบทความนี้มีประโยชน์ ฝากกดแชร์ด้วยนะครับ