Spring Cloud Gateway 使用範例

2022-11-19 15:02:46

Spring Cloud Gateway 使用範例

作者: Grey

原文地址:

部落格園:Spring Cloud Gateway 使用範例

CSDN:Spring Cloud Gateway 使用範例

說明

Spring Cloud Gateway 用於構建 API 閘道器,基於 Spring WebFlux。

Spring Cloud G 版釋出時,

Spring 官方把 Spring Cloud Gateway 作為 Zuul 1 的替代方案

本文主要通過一個範例介紹了 Spring Cloud Gateway 的基礎使用。

環境

  • JDK 1.8+

  • Maven 3.5+

  • Spring Boot 版本:2.7.5

  • Spring Cloud 版本:2021.0.5

涉及的依賴包

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-circuitbreaker-reactor-resilience4j</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-contract-stub-runner</artifactId>
    <scope>test</scope>
</dependency>

程式碼說明

第一個場景就是請求轉發,例如

請求:http://localhost:8080/jd

直接轉到:http://jd.com:80/jd

請求:http://localhost:8080/greyzeng

直接轉到:http://www.cnblogs.com/greyzeng

請求:http://localhost:8080/error

直接跳轉到自定義的一個錯誤頁面。

只需要做如下設定即可

@Bean
public RouteLocator myRoutes(RouteLocatorBuilder builder, UriConfiguration uriConfiguration) {
    return builder.routes()
                .route(p -> p.path("/jd").uri("http://jd.com:80/"))
                .route(p -> p.path("/greyzeng").uri("http://www.cnblogs.com/"))
                .route(p -> p.path("/error").uri("forward:/fallback"))
                .build();
}
@RequestMapping("/fallback")
public Mono<String> fallback() {
    return Mono.just("fallback");
}

啟動服務,執行 GatewayApplication.java

瀏覽器存取:http://localhost:8080/jdhttp://localhost:8080/greyzeng,會直接跳轉到對應的頁面。

輸入:http://localhost:8080/error,直接跳轉到自定義的/fallback請求服務中。

在轉發過程中,也可以設定一些引數,比如

    @Bean
    public RouteLocator myRoutes(RouteLocatorBuilder builder, UriConfiguration uriConfiguration) {
        final String httpUri = "http://httpbin.org:80";
        return builder.routes()
                .route(p -> p.path("/get").filters(f -> f.addRequestHeader("Hello", "World")).uri(httpUri))
                .build();
    }

在請求: http://localhost:8080/get 這個服務過程中,增加一個 Header 引數

第二個場景就是結合熔斷器的使用,例如:Spring Cloud Circuit Breaker,過濾來自不同的 host 請求,比如,針對來自:*.circuitbreaker.com 的請求,將其轉到統一的例外處理頁面。

    @Bean
    public RouteLocator myRoutes(RouteLocatorBuilder builder, UriConfiguration uriConfiguration) {
        String httpUri = uriConfiguration.getHttpbin();
        return builder.routes()
            
                .route(p -> p.host("*.circuitbreaker.com").filters(f -> f.circuitBreaker(config -> config.setName("mycmd").setFallbackUri("forward:/fallback"))).uri(httpUri))
                .build();
    }

通過如下程式碼進行模擬測試,

import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
import static com.github.tomakehurst.wiremock.client.WireMock.get;
import static com.github.tomakehurst.wiremock.client.WireMock.stubFor;
import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
import static org.assertj.core.api.Assertions.assertThat;


@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, properties = {"httpbin=http://localhost:${wiremock.server.port}"})
@AutoConfigureWireMock(port = 0)
public class GatewayApplicationTest {

    @Autowired
    private WebTestClient webClient;

    @Test
    public void contextLoads() {
        //Stubs
      stubFor(get(urlEqualTo("/delay/3")).willReturn(aResponse().withBody("no fallback").withFixedDelay(3000)));
      webClient.get().uri("/delay/3").header("Host", "www.circuitbreaker.com").exchange().expectStatus().isOk().expectBody().consumeWith(response -> assertThat(response.getResponseBody()).isEqualTo("fallback".getBytes()));
    }
}

簡單說明一下

存取過程中,如果某個請求的 Host 來自於 www.circuitbreaker.com,會直接返回 /fallback 中。

如果 Host 不是 www.circuitbreaker.com,則直接返回正確結果即可。

完整程式碼

spring-cloud-gateway-usage

參考資料

Spring Cloud Gateway

Building a Gateway

重新定義 Spring Cloud 實戰