Mình đã giới thiệu với các bạn về Hystrix và Hystrix Dashboard với những vấn đề mà chúng giải quyết trong một hệ thống Microservices. Đối với những ứng dụng Reactive Web Service, việc sử dụng Hystrix và Hystrix Dashboard sẽ khác một xíu. Hiện tại, annotation @HystrixCommand sẽ không work với các ứng dụng Reactive Web Service mà chúng ta phải sử dụng class HystrixCommands để giải quyết vấn đề của mình. Cụ thể như thế nào? Trong bài viết này, mình sẽ trình bày với các bạn cách sử dụng Hystrix và Hystrix Dashboard từ Spring Cloud Netflix trong ứng dụng Reactive Web Service với Spring WebFlux các bạn nhé!
Để làm ví dụ cho bài viết này, mình sẽ sử dụng Reactive Web Service mà mình đã tạo trong bài viết về Reactive Web Service sử dụng Spring WebFlux.
Mình sẽ expose thêm một request URL trong Reactive Web Service này như sau:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
package com.huongdanjava.springwebfluxannotation; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import reactor.core.publisher.Flux; @RestController public class HelloController { @GetMapping(value = "/hello") public Flux<String> findAll() { return Flux.just("Hello, Huong Dan Java"); } } |
Mình sẽ tạo mới một ứng dụng khác sử dụng WebClient để consume Reactive Web Service trên với Hystrix và Hystrix Dashboard như sau:
Kết quả:
Tiếp theo, mình sẽ thêm mới một request URL sử dụng WebClient để consume Reactive Web Service trong bài viết này. Controller của mình có nội dung như sau:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
package com.huongdanjava.springwebfluxhystrix; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.reactive.function.client.WebClient; import reactor.core.publisher.Flux; @RestController public class SpringWebfluxHystrixController { @RequestMapping(value = "/consume-hello") public String findAll() { String url = "http://localhost:8080"; WebClient webClient = WebClient.create(url); Flux<String> flux = webClient.get() .uri("/hello") .retrieve() .bodyToFlux(String.class); return flux.blockFirst(); } } |
Vì hiện tại Reactive Web Service đang chạy trên port 8080 nên mình sẽ thêm property server.port trong tập tin application.properties của ứng dụng này với giá trị 8081 để ứng dụng này chạy trên port khác.
1 |
server.port=8081 |
Chạy cả 2 ứng dụng và kết quả khi mình request tới địa chỉ http://localhost:8081/consume-hello sẽ như sau:
OK, bây giờ mình sẽ sử dụng Hystrix để hiện thực Circuit Breaker, khi Reactive Web Service không available thì ứng dụng của chúng ta sẽ trả về giá trị mặc định các bạn nhé.
Để làm được điều này, mình sẽ thêm annotation @EnableCircuitBreaker vào class main của ứng dụng như sau:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
package com.huongdanjava.springwebfluxhystrix; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker; @SpringBootApplication @EnableCircuitBreaker public class SpringWebfluxHystrixApplication { public static void main(String[] args) { SpringApplication.run(SpringWebfluxHystrixApplication.class, args); } } |
Như mình đã nói, annotation @HystrixCommand hiện tại chưa work với Spring WebFlux mà chúng ta sẽ sử dụng class HystrixCommands như sau:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
package com.huongdanjava.springwebfluxhystrix; import org.springframework.cloud.netflix.hystrix.HystrixCommands; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.reactive.function.client.WebClient; import reactor.core.publisher.Flux; @RestController public class SpringWebfluxHystrixController { @RequestMapping(value = "/consume-hello") public String findAll() { String url = "http://localhost:8080"; WebClient webClient = WebClient.create(url); Flux<String> flux = webClient.get() .uri("/hello") .retrieve() .bodyToFlux(String.class); Flux<String> fluxAsDefault = HystrixCommands.from(flux) .commandName("hello") .fallback(Flux.just("Hello, Khanh Nguyen")) .toFlux(); return fluxAsDefault.blockFirst(); } } |
Như các bạn thấy, sử dụng HystrixCommands chúng ta sẽ tạo một fallback từ đối tượng Flux hoặc Mono được trả về. Command name ở đây là tên gọi sẽ dùng để phân biệt, giúp chúng ta có thể biết được calling request URL nào đang có vấn đề.
Nếu bây giờ các bạn stop Reactive Web Service, restart lại ứng dụng rồi request lại URL http://localhost:8081/consume-hello, kết quả sẽ như sau:
Bây giờ chúng ta thử cấu hình để sử dụng Hystrix Dashboard các bạn nhé.
Chúng ta cần thêm annotation @EnableHystrixDashboard trong class main của ứng dụng như sau:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
package com.huongdanjava.springwebfluxhystrix; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker; import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard; @SpringBootApplication @EnableCircuitBreaker @EnableHystrixDashboard public class SpringWebfluxHystrixApplication { public static void main(String[] args) { SpringApplication.run(SpringWebfluxHystrixApplication.class, args); } } |
Tiếp theo chúng ta sẽ cấu hình để Actuator enable API cung cấp data cho Hystrix Dashboard trong tập tin application.properties như sau:
1 |
management.endpoints.web.exposure.include=* |
OK, bây giờ các bạn thử truy cập vào đường dẫn http://localhost:8081/hystrix, nhập http://localhost:8081/actuator/hystrix.stream, nhấn “Monitor Stream” rồi request tới địa chỉ http://localhost:8081/consume-hello, các bạn sẽ thấy Hystrix Dashboard hiển thị như sau:
Start lại Reactive Web Service, các bạn sẽ thấy kết quả như sau trong Hystrix Dashboard khi request tới http://localhost:8081/consume-hello:
Không lỗi nào được hiển thị cả, nhưng có vẻ hiện tại với Spring WebFlux, Hystrix Dashboard chưa hiển thị được số request success các bạn ạ.