1. 程式人生 > 實用技巧 >SpringCloud-Gateway元件使用

SpringCloud-Gateway元件使用

1.什麼是服務閘道器

1.說明

  • 閘道器統一服務入口,可方便實現對平臺眾多服務介面進行管控,對訪問服務的身份認證、防報文重放與防資料篡改、功能呼叫的業務鑑權、響應資料的脫敏、流量與併發控制,甚至基於API呼叫的計量或者計費等等。

  • 閘道器 = 路由轉發 + 過濾器
    路由轉發:接收一切外界請求,轉發到後端的微服務上去; 在服務閘道器中可以完成一系列的橫切功能,例如許可權校驗、限流以及監控等,這些都可以通過過濾器完成

2.為什麼需要閘道器

  • 1.閘道器可以實現服務的統一管理
  • 2.閘道器可以解決微服務中通用程式碼的冗餘問題(如許可權控制,流量監控,限流等)

3.閘道器元件在微服務中架構

2.服務閘道器元件

1.zuul

Zuul is the front door for all requests from devices and web sites to the backend of the Netflix streaming application. As an edge service application, Zuul is built to enable dynamic routing, monitoring, resiliency and security.

  1. 原文翻譯

    • https://github.com/Netflix/zuul/wiki
    • zul是從裝置和網站到Netflix流媒體應用程式後端的所有請求的前門。作為一個邊緣服務應用程式,zul被構建為支援動態路由、監視、彈性和安全性。
  2. zuul版本說明

    • 目前zuul元件已經從1.0更新到2.0,但是作為springcloud官方不再推薦使用zuul2.0,但是依然支援zuul2.
  3. springcloud 官方整合zuul文件

2.gateway

This project provides a library for building an API Gateway on top of Spring MVC. Spring Cloud Gateway aims to provide a simple, yet effective way to route to APIs and provide cross cutting concerns to them such as: security, monitoring/metrics, and resiliency.

  1. 原文翻譯

    • https://spring.io/projects/spring-cloud-gateway
    • 這個專案提供了一個在springmvc之上構建API閘道器的庫。springcloudgateway旨在提供一種簡單而有效的方法來路由到api,併為api提供橫切關注點,比如:安全性、監控/度量和彈性。
  2. 特性

    • 基於springboot2.x 和 spring webFlux 和 Reactor 構建 響應式非同步非阻塞IO模型
    • 動態路由
    • 請求過濾

建立一個新的專案,根據之前寫的環境搭建方式

3.開發閘道器動態路由

  • 閘道器配置有兩種方式一種是快捷方式,一種是完全展開方式

1.建立專案引入閘道器依賴

<!--引入gateway閘道器依賴-->
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>

完整的pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.5.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <groupId>com.md</groupId>
    <artifactId>05-gateway8989</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>05-gateway8989</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Hoxton.SR6</spring-cloud.version>
    </properties>

    <dependencies>
       <!--使用閘道器的時候web包需要移除掉-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!--引入gateway閘道器依賴-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>

        <!--引入consul依賴-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-consul-discovery</artifactId>
        </dependency>

        <!-- 這個包是用做健康度監控的-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

    </dependencies>

    <!--全域性管理springcloud版本,並不會引入具體依賴-->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

快捷方式配置路由

2.編寫閘道器配置

spring:
  application:
    name: gateway
  cloud:
    consul:
      host: localhost
      port: 8500
      discovery:
        service-name: ${spring.application.name}
    gateway:
      routes:
        - id: user_route    # 指定路由的唯一標識
          uri: http://localhost:9999/  # 指定路由服務的地址
          predicates:  # 指定路由的規則
            - Path=/user/**

        - id: product_route
          uri: http://localhost:9998/
          predicates:
            - Path=/product/**

server:
  port: 8989

3.啟動gateway閘道器專案

  • 直接啟動報錯:

  • 在啟動日誌中發現,gateway為了效率使用webflux進行非同步非阻塞模型的實現,因此和原來的web包衝突,去掉原來的web即可

  • 再次啟動成功啟動

4.測試閘道器路由轉發

使用之前寫的寫的,可以看前面幾篇文章

java方式配置路由(瞭解)

環境還是和上面的一樣

@Configuration
public class GatewayConfig {
    @Bean
    public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
        return builder.routes()
                .route("order_route", r -> r.path("/order/**")
                        .uri("http://localhost:9997/"))
                .build();
    }
}

4.檢視閘道器路由規則列表

1.說明

  • gateway提供路由訪問規則列表的web介面,但是預設是關閉的,如果想要檢視服務路由規則可以在配置檔案中開啟
management:
  endpoints:
    web:
      exposure:
        include: "*"   #開啟所有web端點暴露

訪問路由管理列表地址

3.配置路由服務負載均衡

1.說明

  • 現有路由配置方式,都是基於服務地址寫死的路由轉發,能不能根據服務名稱進行路由轉發同時實現負載均衡的呢?

2.動態路由以及負載均衡轉發配置

spring:
  application:
    name: gateway
  cloud:
    consul:
      host: localhost
      port: 8500
      discovery:
        service-name: ${spring.application.name}
    gateway:
      routes:
        - id: user_route    # 指定路由的唯一標識
#          uri: http://localhost:9999/  # 指定路由服務的地址

          # lb代表轉發後臺服務使用負載均衡,users代表服務註冊中心上的服務名
          uri: lb://users
          predicates:  # 指定路由的規則
            - Path=/user/**

        - id: product_route
#          uri: http://localhost:9998/

          # lb代表負載均衡轉發路由,products代表服務註冊中心上的服務名
          uri: lb://products
          predicates:
            - Path=/product/**

      # 開啟根據服務名動態獲取路由地址
      discovery:
        locator:
          enabled: true

server:
  port: 8989

#開啟所有web端點暴露
management:
  endpoints:
    web:
      exposure:
        include: "*"

此時訪問就實現了負載均衡的效果

4.常用路由predicate(斷言,驗證)

1.Gateway支援多種方式的predicate

After、Before、Between用於商城活動的時候指定日期才能訪問

2.使用predicate

spring:
  application:
    name: gateway
  cloud:
    consul:
      host: localhost
      port: 8500
    gateway:
      routes:
        - id: user_route
          #uri: http://localhost:9999/
          uri: lb://users
          predicates:
            - Path=/user/**
            - After=2020-12-21T11:39:33.993+08:00[Asia/Shanghai]
            - Cookie=username,[A-Za-z0-9]+
            - Header=X-Request-Id, \d+

5.常用的Filter以及自定義filter

1.作用

  • 當我們有很多個服務時,比如下圖中的user-service、order-service、product-service等服務,客戶端請求各個服務的Api時,每個服務都需要做相同的事情,比如鑑權、限流、日誌輸出等。


2.使用內建過濾器

spring:
  application:
    name: gateway
  cloud:
    gateway:
      routes:
        - id: product_route
          #uri: http://localhost:9998/
          uri: lb://products     # lb: 使用負載均衡策略   products代表註冊中心的具體服務名
          predicates:
            - Path=/product/**
            #- After=2020-07-30T09:45:49.078+08:00[Asia/Shanghai]
          filters:
          # 為每個請求新增引數id=12
            - AddRequestParameter=id,12
          # 增加響應頭  
            - AddResponseHeader=username,chenyn

3.使用自定義filter

@Configuration
@Slf4j
public class CustomGlobalFilter implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        log.info("進入自定義的filter");
        if(exchange.getRequest().getQueryParams().get("username")!=null){
            log.info("使用者身份資訊合法,放行請求繼續執行!!!");
            return chain.filter(exchange);
        }
        log.info("非法使用者,拒絕訪問!!!");
       return exchange.getResponse().setComplete();
    }

    @Override
    public int getOrder() {  //filter 數字越小filter越先執行
        return -1;           //-1  最先執行
    }
}

自定義全域性filter