spring-boot - 如何在 Spring Boot 中将 Resilience4j 断路器与 WebFlux 一起使用
问题描述
我有调用下游服务 B 的服务 A。
服务 A 代码
@RestController
@RequestMapping(value = "", produces = MediaType.APPLICATION_JSON_VALUE)
public class GreetingController {
private final GreetingService greetingService;
public GreetingController(GreetingService greetingService){
this.greetingService = greetingService;
}
@GetMapping(value = "/greetings")
public Mono<String> getGreetings() {
return greetingService.callServiceB();
}
}
@Component
@RequiredArgsConstructor
public class GreetingService {
CircuitBreaker circuitBreaker = CircuitBreaker.ofDefaults("greetingService");
Callable<Mono<String>> callable = CircuitBreaker.decorateCallable(circuitBreaker, this::clientCall);
Future<Mono<String>> future = Executors.newSingleThreadExecutor().submit(callable);
public Mono<String> callServiceB() {
try {
return future.get();
} catch (CircuitBreakerOpenException | InterruptedException | ExecutionException ex){
return Mono.just("Service is down!");
}
}
private final String url = "/v1/holidaysgreetings";
private Mono<String> clientCall(){
WebClient client = WebClient.builder().baseUrl("http://localhost:8080").build();
return client
.get()
.uri(url)
.retrieve()
.bodyToMono(String.class);
}
当我关闭下游服务 B(在 localhost:8080 上运行)并/greetings
在课堂上点击端点GreetingsController
以查看我的断路器是否正常工作时,我得到了这个令人讨厌的错误
2021-06-28 21:27:31.431 ERROR 10285 --- [nio-8081-exec-7] o.a.c.c.C.[.[.[.[dispatcherServlet]: Servlet.service() for servlet [dispatcherServlet] in context with path [/v1/holidaysgreetings]
threw exception [Request processing failed; nested exception is org.springframework.web.reactive.function.client.WebClientRequestException: Connection refused: localhost/127.0.0.1:8080;
nested exception is io.netty.channel.AbstractChannel$AnnotatedConnectException: Connection refused: localhost/127.0.0.1:8080] with root cause
java.net.ConnectException: Connection refused
任何人都知道我为什么会得到这个?我在这里缺少什么?我是否正确实施断路器?
解决方案
您将反应式库与常规的非反应式库混合在一起。如果您打算使用spring-webflux
它,最好将其reactor-resilience4j
与常规reactor-adapter
库一起使用。
使用这些导入:
implementation 'org.springframework.boot:spring-boot-starter-webflux'
implementation 'org.springframework.cloud:spring-cloud-starter-circuitbreaker-reactor-resilience4j'
implementation "io.projectreactor.addons:reactor-adapter:${reactorVersion}"
您也没有创建您可以依赖的断路器服务。创建它后,您可以调用“ Mono run(Mono toRun, Function<Throwable, Mono> fallback) ”(如果您愿意,可以调用返回 Flux 的那个)来执行您的服务并提供回退。
这是演示代码中的一个示例。
@RestController
public class CompletableFutureDemoController {
Logger LOG = LoggerFactory.getLogger(CompletableFutureDemoController.class);
private CompletableFutureHttpBinService httpBin;
private ReactiveCircuitBreakerFactory reactiveCircuitBreakerFactory;
public CompletableFutureDemoController(CompletableFutureHttpBinService httpBin, ReactiveCircuitBreakerFactory reactiveCircuitBreakerFactory) {
this.httpBin = httpBin;
this.reactiveCircuitBreakerFactory = reactiveCircuitBreakerFactory;
}
@GetMapping("/completablefuture/delay/{seconds}")
public Mono<Map> delay(@PathVariable int seconds) {
return reactiveCircuitBreakerFactory.create("completablefuturedelay")
.run(Mono.fromFuture(httpBin.delay(seconds)), t -> {
LOG.warn("delay call failed error", t);
Map<String, String> fallback = new HashMap();
fallback.put("hello", "world");
return Mono.just(fallback);
}
);
}
}
推荐阅读
- java - 安装jdk的问题
- javascript - 如何使用 Node JS 从 json 中了解对象类型
- c# - 使用 cshtml 禁用输入
- r - R - 几何布朗运动建模
- json - Groovy - Read JSON value using variable
- android - 在 TextView 中设置长文本将挂起 ui 线程(更具体地说,在 Android 的 nComputeLineBreaks() 调用中)
- python - 根据中间数据框删除行
- angular - Angular NgModule 能否提供一个 style.scss 文件供导入它的人使用?
- sql - 为表数据和列定义生成 xml
- tsql - 提取最大日期或其他日期