9.2.3 使用 Spring WebFlux 定义回退 REST API
当我们将 CircuitBreaker 过滤器添加到 catalog-route 时,我们为 fallbackUri 属性定义了一个值,以便在电路处于打开状态时将请求转发到 /catalog-fallback 端点。由于 Retry 过滤器也应用于该路由,即使给定请求的所有重试尝试都失败,回退端点也会被调用。是时候定义该端点了。
正如我在前面章节中提到的,Spring 支持使用 @RestController 类或路由函数定义 REST 端点。让我们使用函数式方式声明回退端点。
在 Edge Service 项目中的新 com.polarbookshop.edgeservice.web 包中,创建一个新的 WebEndpoints 类。Spring WebFlux 中的函数式端点定义为 RouterFunction
代码清单 9.9 当 Catalog Service 宕机时的回退端点
package com.polarbookshop.edgeservice.web;
import reactor.core.publisher.Mono;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.RouterFunctions;
import org.springframework.web.reactive.function.server.ServerResponse;
@Configuration
public class WebEndpoints {
@Bean // 函数式 REST 端点在 bean 中定义
public RouterFunction<ServerResponse> routerFunction() {
return RouterFunctions.route() // 提供流畅的 API 来构建路由
// 用于处理 GET 端点的回退响应
.GET("/catalog-fallback", request ->
ServerResponse.ok().body(Mono.just(""), String.class))
// 用于处理 POST 端点的回退响应
.POST("/catalog-fallback", request ->
ServerResponse.status(HttpStatus.SERVICE_UNAVAILABLE).build())
.build(); // 构建函数式端点
}
}
为简单起见,GET 请求的回退返回空字符串,而 POST 请求的回退返回 HTTP 503 错误。在真实场景中,你可能想要根据上下文采用不同的回退策略,包括抛出自定义异常以便从客户端处理,或返回原始请求缓存中保存的最后一个值。
到目前为止,我们已经使用了重试、超时、断路器和故障转移(回退)。在下一节中,我将扩展如何一起使用所有这些弹性模式。